Merge "Cleaned up LoadBalancer::getConnection"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 12 Dec 2014 02:47:39 +0000 (02:47 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 12 Dec 2014 02:47:39 +0000 (02:47 +0000)
235 files changed:
HISTORY
README
RELEASE-NOTES-1.25
autoload.php
composer.json
docs/hooks.txt
includes/Autopromote.php
includes/Block.php
includes/ChangeTags.php
includes/Collation.php
includes/Defines.php
includes/EditPage.php
includes/Export.php
includes/FileDeleteForm.php
includes/GitInfo.php
includes/GlobalFunctions.php
includes/Import.php
includes/Linker.php
includes/MWNamespace.php
includes/MWTimestamp.php
includes/MagicWord.php
includes/MediaWiki.php
includes/MimeMagic.php
includes/MovePage.php
includes/OutputHandler.php
includes/OutputPage.php
includes/Preferences.php
includes/PrefixSearch.php
includes/ProtectionForm.php
includes/Revision.php
includes/Sanitizer.php
includes/Setup.php
includes/Title.php
includes/TitleArray.php
includes/User.php
includes/UserArray.php
includes/WebRequest.php
includes/WebResponse.php
includes/Xml.php
includes/actions/EditAction.php
includes/actions/FormAction.php
includes/actions/HistoryAction.php
includes/actions/InfoAction.php
includes/actions/RawAction.php
includes/actions/WatchAction.php
includes/api/ApiBase.php
includes/api/ApiCreateAccount.php
includes/api/ApiEditPage.php
includes/api/ApiFormatBase.php
includes/api/ApiHelp.php
includes/api/ApiLogin.php
includes/api/ApiLogout.php
includes/api/ApiMain.php
includes/api/ApiOpenSearch.php
includes/api/ApiPageSet.php
includes/api/ApiParse.php
includes/api/ApiPatrol.php
includes/api/ApiQuery.php
includes/api/ApiQueryInfo.php
includes/api/ApiQueryRecentChanges.php
includes/api/ApiQueryRevisions.php
includes/api/ApiQueryRevisionsBase.php
includes/api/ApiQuerySiteinfo.php
includes/api/ApiQueryTokens.php
includes/api/ApiQueryUsers.php
includes/api/ApiRsd.php
includes/api/ApiStashEdit.php
includes/api/ApiTokens.php
includes/api/ApiUndelete.php
includes/api/i18n/be-tarask.json
includes/api/i18n/bs.json [new file with mode: 0644]
includes/api/i18n/ksh.json
includes/api/i18n/mg.json [new file with mode: 0644]
includes/api/i18n/mk.json
includes/api/i18n/nl.json
includes/api/i18n/te.json [new file with mode: 0644]
includes/api/i18n/zh-hans.json
includes/api/i18n/zh-hant.json
includes/cache/BacklinkCache.php
includes/cache/HTMLFileCache.php
includes/cache/LocalisationCache.php
includes/cache/MessageCache.php
includes/cache/ResourceFileCache.php
includes/changes/ChangesList.php
includes/changes/OldChangesList.php
includes/changes/RecentChange.php
includes/content/AbstractContent.php
includes/content/ContentHandler.php
includes/content/WikitextContent.php
includes/context/RequestContext.php
includes/db/Database.php
includes/db/DatabaseMysqlBase.php
includes/db/DatabaseOracle.php
includes/db/DatabaseUtility.php
includes/db/LoadBalancer.php
includes/deferred/LinksUpdate.php
includes/deferred/SearchUpdate.php
includes/diff/DifferenceEngine.php
includes/exception/MWExceptionHandler.php
includes/filerepo/file/File.php
includes/filerepo/file/LocalFile.php
includes/gallery/ImageGalleryBase.php
includes/gallery/TraditionalImageGallery.php
includes/installer/DatabaseUpdater.php
includes/installer/i18n/te.json
includes/installer/i18n/vi.json
includes/installer/i18n/zh-hant.json
includes/interwiki/Interwiki.php
includes/libs/GenericArrayObject.php
includes/libs/IPSet.php
includes/libs/ScopedCallback.php
includes/libs/XmlTypeCheck.php
includes/logging/LogEventsList.php
includes/logging/LogFormatter.php
includes/mail/EmailNotification.php
includes/mail/UserMailer.php
includes/media/FormatMetadata.php
includes/media/MediaHandler.php
includes/media/MediaTransformOutput.php
includes/media/TransformationalImageHandler.php
includes/media/XMP.php
includes/media/XMPInfo.php
includes/page/Article.php
includes/page/CategoryPage.php
includes/page/ImagePage.php
includes/page/WikiPage.php
includes/parser/LinkHolderArray.php
includes/parser/MWTidy.php
includes/parser/Parser.php
includes/parser/ParserOptions.php
includes/profiler/ProfilerStandard.php
includes/profiler/ProfilerXhprof.php
includes/profiler/SectionProfiler.php
includes/rcfeed/IRCColourfulRCFeedFormatter.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderContext.php
includes/resourceloader/ResourceLoaderImage.php [new file with mode: 0644]
includes/resourceloader/ResourceLoaderImageModule.php [new file with mode: 0644]
includes/resourceloader/ResourceLoaderSkinModule.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/revisiondelete/RevDelArchiveList.php
includes/revisiondelete/RevDelArchivedFileList.php
includes/revisiondelete/RevDelFileList.php
includes/revisiondelete/RevDelLogList.php
includes/revisiondelete/RevDelRevisionList.php
includes/revisiondelete/RevisionDeleteUser.php
includes/search/SearchEngine.php
includes/search/SearchResult.php
includes/skins/BaseTemplate.php
includes/skins/Skin.php
includes/skins/SkinTemplate.php
includes/specialpage/ChangesListSpecialPage.php
includes/specialpage/FormSpecialPage.php
includes/specialpage/ImageQueryPage.php
includes/specialpage/PageQueryPage.php
includes/specialpage/QueryPage.php
includes/specialpage/RedirectSpecialPage.php
includes/specialpage/SpecialPage.php
includes/specialpage/SpecialPageFactory.php
includes/specialpage/WantedQueryPage.php
includes/specials/SpecialBlock.php
includes/specials/SpecialBlockList.php
includes/specials/SpecialBooksources.php
includes/specials/SpecialChangeEmail.php
includes/specials/SpecialChangePassword.php
includes/specials/SpecialContributions.php
includes/specials/SpecialDeletedContributions.php
includes/specials/SpecialEditWatchlist.php
includes/specials/SpecialEmailuser.php
includes/specials/SpecialImport.php
includes/specials/SpecialListusers.php
includes/specials/SpecialLog.php
includes/specials/SpecialLonelypages.php
includes/specials/SpecialMergeHistory.php
includes/specials/SpecialMovepage.php
includes/specials/SpecialNewpages.php
includes/specials/SpecialPageLanguage.php
includes/specials/SpecialPasswordReset.php
includes/specials/SpecialRandompage.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialResetTokens.php
includes/specials/SpecialSearch.php
includes/specials/SpecialStatistics.php
includes/specials/SpecialUndelete.php
includes/specials/SpecialUpload.php
includes/specials/SpecialUserlogin.php
includes/specials/SpecialUserlogout.php
includes/specials/SpecialUserrights.php
includes/specials/SpecialVersion.php
includes/specials/SpecialWantedfiles.php
includes/specials/SpecialWantedpages.php
includes/specials/SpecialWatchlist.php
includes/specials/SpecialWhatlinkshere.php
includes/upload/UploadBase.php
includes/upload/UploadFromUrl.php
includes/utils/IP.php
languages/Language.php
languages/i18n/be-tarask.json
languages/i18n/bn.json
languages/i18n/bs.json
languages/i18n/ce.json
languages/i18n/cs.json
languages/i18n/de.json
languages/i18n/egl.json
languages/i18n/es.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/gl.json
languages/i18n/hr.json
languages/i18n/it.json
languages/i18n/ka.json
languages/i18n/lb.json
languages/i18n/mk.json
languages/i18n/ml.json
languages/i18n/nap.json
languages/i18n/pms.json
languages/i18n/ro.json
languages/i18n/ru.json
languages/i18n/sl.json
languages/i18n/sv.json
languages/i18n/te.json
languages/i18n/th.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/messages/MessagesHe.php
maintenance/Maintenance.php
maintenance/checkLess.php
maintenance/findHooks.php
maintenance/storage/recompressTracked.php
maintenance/updateArticleCount.php
resources/Resources.php
resources/src/mediawiki.action/mediawiki.action.edit.stash.js
tests/parser/parserTests.txt
tests/phpunit/includes/api/format/ApiFormatWddxTest.php
tests/qunit/suites/resources/jquery/jquery.mwExtension.test.js

diff --git a/HISTORY b/HISTORY
index 78ece33..64d409f 100644 (file)
--- a/HISTORY
+++ b/HISTORY
@@ -462,9 +462,9 @@ changes to languages because of Bugzilla reports.
   meaning that JavaScript is no longer executed in these browser versions.
 * Browser support for Opera 11 lowered from Grade A to Grade C.
 * Removed IEFixes module which existed purely to provide support for MSIE versions
+  below 7 (conditionally loaded only for those browsers).
 * Deprecated SpecialPageFactory::getList() in favor of
   SpecialPageFactory::getNames()
-  below 7 (conditionally loaded only for those browsers).
 * Action::checkCanExecute() no longer has a return value.
 * Removed cleanupForIRC(), loadFromCurRow(), newFromCurRow(), notifyRC2UDP()
   and sendToUDP() from RecentChange.php. (deprecated since 1.22)
diff --git a/README b/README
index 282ee6c..29577bc 100644 (file)
--- a/README
+++ b/README
@@ -1,17 +1,17 @@
 == MediaWiki ==
 
-MediaWiki is a popular and free, open-source wiki software package written in
-PHP. It serves as the platform for Wikipedia and the other projects of the Wikimedia
-Foundation, which deliver content in over 280 languages to more than half a billion
-people each month. MediaWiki's reliability and robust feature set have earned it a
-large and vibrant community of third-party users and developers.
+MediaWiki is a free and open-source wiki software package written in PHP. It
+serves as the platform for Wikipedia and the other projects of the Wikimedia
+Foundation, which deliver content in over 280 languages to more than half a
+billion people each month. MediaWiki's reliability and robust feature set have
+earned it a large and vibrant community of third-party users and developers.
 
 MediaWiki is:
 
-* feature-rich and extensible, both on-wiki and with over 2,000 extensions;
+* feature-rich and extensible, both on-wiki and with hundreds of extensions;
 * scalable and suitable for both small and large sites;
-* available in your language; and
-* simple to install, working on most hardware/software combinations.
+* simple to install, working on most hardware/software combinations; and
+* available in your language.
 
 For system requirements, installation, and upgrade details, see the files
 RELEASE-NOTES, INSTALL, and UPGRADE.
@@ -23,7 +23,7 @@ RELEASE-NOTES, INSTALL, and UPGRADE.
 * Seeking help from a person?
 ** https://www.mediawiki.org/wiki/Communication
 * Looking to file a bug report or a feature request?
-** https://bugzilla.wikimedia.org/
+** https://bugs.mediawiki.org/
 * Interested in helping out?
 ** https://www.mediawiki.org/wiki/How_to_contribute
 
index 06d2d66..339e677 100644 (file)
@@ -271,6 +271,8 @@ changes to languages because of Bugzilla reports.
 ** In source text of the form '{$A}'{$B}' or `{$A}`{$B}`, where variable A
    does not exist yet variable B does, the latter may not be replaced.
    However, this difference is unlikely to arise in practice.
+* (T67278) RFC, PMID, and ISBN "magic links" must be surrounded by non-word
+  characters on both sides.
 
 == Compatibility ==
 
index 8003284..175ab42 100644 (file)
@@ -951,6 +951,8 @@ $wgAutoloadLocalClasses = array(
        'ResourceLoaderFileModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderFileModule.php',
        'ResourceLoaderFilePageModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderFilePageModule.php',
        'ResourceLoaderFilePath' => __DIR__ . '/includes/resourceloader/ResourceLoaderFilePath.php',
+       'ResourceLoaderImage' => __DIR__ . '/includes/resourceloader/ResourceLoaderImage.php',
+       'ResourceLoaderImageModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderImageModule.php',
        'ResourceLoaderLanguageDataModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderLanguageDataModule.php',
        'ResourceLoaderLanguageNamesModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderLanguageNamesModule.php',
        'ResourceLoaderModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderModule.php',
@@ -959,9 +961,9 @@ $wgAutoloadLocalClasses = array(
        'ResourceLoaderSkinModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderSkinModule.php',
        'ResourceLoaderStartUpModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderStartUpModule.php',
        'ResourceLoaderUserCSSPrefsModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php',
+       'ResourceLoaderUserDefaultsModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserDefaultsModule.php',
        'ResourceLoaderUserGroupsModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserGroupsModule.php',
        'ResourceLoaderUserModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserModule.php',
-       'ResourceLoaderUserDefaultsModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserDefaultsModule.php',
        'ResourceLoaderUserOptionsModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserOptionsModule.php',
        'ResourceLoaderUserTokensModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserTokensModule.php',
        'ResourceLoaderWikiModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderWikiModule.php',
index 0634c2d..dcb21af 100644 (file)
@@ -11,7 +11,7 @@
        ],
        "license": "GPL-2.0",
        "support": {
-               "issues": "https://bugzilla.wikimedia.org/",
+               "issues": "https://bugs.mediawiki.org/",
                "irc": "irc://irc.freenode.net/mediawiki",
                "wiki": "https://www.mediawiki.org/"
        },
index f8b077e..4a9e0b8 100644 (file)
@@ -776,12 +776,10 @@ $out: OutputPage object
 'BeforeParserFetchFileAndTitle': Before an image is rendered by Parser.
 $parser: Parser object
 $nt: the image title
-&$options: array of options to RepoGroup::findFile
+&$options: array of options to RepoGroup::findFile. If it contains 'broken'
+  as a key then the file will appear as a broken thumbnail.
 &$descQuery: query string to add to thumbnail URL
 
-FIXME: Where does the below sentence fit in?
-If 'broken' is a key in $options then the file will appear as a broken thumbnail.
-
 'BeforeParserFetchTemplateAndtitle': Before a template is fetched by Parser.
 $parser: Parser object
 $title: title of the template
@@ -1048,7 +1046,8 @@ This may be triggered by the EditPage or any other facility that modifies page c
 Use the $status object to indicate whether the edit should be allowed, and to provide
 a reason for disallowing it. Return false to abort the edit, and true to continue.
 Returning true if $status->isOK() returns false means "don't save but continue user
-interaction", e.g. show the edit form.
+interaction", e.g. show the edit form. $status->apiHookResult can be set to an array
+to be returned by api.php action=edit. This is used to deliver captchas.
 $context: object implementing the IContextSource interface.
 $content: content of the edit box, as a Content object.
 $status: Status object to represent errors, etc.
index 81f3b7a..d492d19 100644 (file)
@@ -43,7 +43,7 @@ class Autopromote {
                        }
                }
 
-               wfRunHooks( 'GetAutoPromoteGroups', array( $user, &$promote ) );
+               Hooks::run( 'GetAutoPromoteGroups', array( $user, &$promote ) );
 
                return $promote;
        }
@@ -197,7 +197,7 @@ class Autopromote {
                                return in_array( 'bot', User::getGroupPermissions( $user->getGroups() ) );
                        default:
                                $result = null;
-                               wfRunHooks( 'AutopromoteCondition', array( $cond[0],
+                               Hooks::run( 'AutopromoteCondition', array( $cond[0],
                                        array_slice( $cond, 1 ), $user, &$result ) );
                                if ( $result === null ) {
                                        throw new MWException( "Unrecognized condition {$cond[0]} for autopromotion!" );
index 3c80035..9079fb0 100644 (file)
@@ -113,7 +113,7 @@ class Block {
                        $this->forcedTargetID = $user; // needed for foreign users
                }
                if ( $by ) { // local user
-                       $this->setBlocker( User::newFromID( $by ) );
+                       $this->setBlocker( User::newFromId( $by ) );
                } else { // foreign user
                        $this->setBlocker( $byText );
                }
@@ -366,7 +366,7 @@ class Block {
        protected function initFromRow( $row ) {
                $this->setTarget( $row->ipb_address );
                if ( $row->ipb_by ) { // local user
-                       $this->setBlocker( User::newFromID( $row->ipb_by ) );
+                       $this->setBlocker( User::newFromId( $row->ipb_by ) );
                } else { // foreign user
                        $this->setBlocker( $row->ipb_by_text );
                }
@@ -580,7 +580,7 @@ class Block {
                if ( $this->isAutoblocking() && $this->getType() == self::TYPE_USER ) {
                        wfDebug( "Doing retroactive autoblocks for " . $this->getTarget() . "\n" );
 
-                       $continue = wfRunHooks(
+                       $continue = Hooks::run(
                                'PerformRetroactiveAutoblock', array( $this, &$blockIds ) );
 
                        if ( $continue ) {
@@ -693,7 +693,7 @@ class Block {
                }
 
                # Allow hooks to cancel the autoblock.
-               if ( !wfRunHooks( 'AbortAutoblock', array( $autoblockIP, &$this ) ) ) {
+               if ( !Hooks::run( 'AbortAutoblock', array( $autoblockIP, &$this ) ) ) {
                        wfDebug( "Autoblock aborted by hook.\n" );
                        return false;
                }
index 87c6ce5..9ee2460 100644 (file)
@@ -320,7 +320,7 @@ class ChangeTags {
                        $emptyTags[] = $row->vt_tag;
                }
 
-               wfRunHooks( 'ListDefinedTags', array( &$emptyTags ) );
+               Hooks::run( 'ListDefinedTags', array( &$emptyTags ) );
 
                $emptyTags = array_filter( array_unique( $emptyTags ) );
 
index 1c2c2db..dac3e93 100644 (file)
@@ -59,7 +59,7 @@ abstract class Collation {
 
                                # Provide a mechanism for extensions to hook in.
                                $collationObject = null;
-                               wfRunHooks( 'Collation::factory', array( $collationName, &$collationObject ) );
+                               Hooks::run( 'Collation::factory', array( $collationName, &$collationObject ) );
 
                                if ( $collationObject instanceof Collation ) {
                                        return $collationObject;
index d0c2226..d63d5ca 100644 (file)
@@ -2,10 +2,6 @@
 /**
  * A few constants that might be needed during LocalSettings.php.
  *
- * Note: these constants must all be resolvable at compile time by HipHop,
- * since this file will not be executed during request startup for a compiled
- * MediaWiki.
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -216,6 +212,7 @@ define( 'MW_SUPPORTS_EDITFILTERMERGED', 1 );
 define( 'MW_SUPPORTS_PARSERFIRSTCALLINIT', 1 );
 define( 'MW_SUPPORTS_LOCALISATIONCACHE', 1 );
 define( 'MW_SUPPORTS_CONTENTHANDLER', 1 );
+define( 'MW_EDITFILTERMERGED_SUPPORTS_API', 1 );
 /**@}*/
 
 /** Support for $wgResourceModules */
index db2e442..2155c1b 100644 (file)
@@ -463,7 +463,7 @@ class EditPage {
        function edit() {
                global $wgOut, $wgRequest, $wgUser;
                // Allow extensions to modify/prevent this form or submission
-               if ( !wfRunHooks( 'AlternateEdit', array( $this ) ) ) {
+               if ( !Hooks::run( 'AlternateEdit', array( $this ) ) ) {
                        return;
                }
 
@@ -558,9 +558,9 @@ class EditPage {
                        }
 
                        if ( !$this->mTitle->getArticleID() ) {
-                               wfRunHooks( 'EditFormPreloadText', array( &$this->textbox1, &$this->mTitle ) );
+                               Hooks::run( 'EditFormPreloadText', array( &$this->textbox1, &$this->mTitle ) );
                        } else {
-                               wfRunHooks( 'EditFormInitialText', array( $this ) );
+                               Hooks::run( 'EditFormInitialText', array( $this ) );
                        }
 
                }
@@ -627,7 +627,7 @@ class EditPage {
                        throw new PermissionsError( $action, $permErrors );
                }
 
-               wfRunHooks( 'EditPage::showReadOnlyForm:initial', array( $this, &$wgOut ) );
+               Hooks::run( 'EditPage::showReadOnlyForm:initial', array( $this, &$wgOut ) );
 
                $wgOut->setRobotPolicy( 'noindex,nofollow' );
                $wgOut->setPageTitle( wfMessage(
@@ -929,7 +929,7 @@ class EditPage {
                        $this->section === 'new' ? 'MediaWiki:addsection-editintro' : '' );
 
                // Allow extensions to modify form data
-               wfRunHooks( 'EditPage::importFormData', array( $this, $request ) );
+               Hooks::run( 'EditPage::importFormData', array( $this, $request ) );
 
                wfProfileOut( __METHOD__ );
        }
@@ -1368,7 +1368,7 @@ class EditPage {
                                $sectionanchor = $resultDetails['sectionanchor'];
 
                                // Give extensions a chance to modify URL query on update
-                               wfRunHooks(
+                               Hooks::run(
                                        'ArticleUpdateBeforeRedirect',
                                        array( $this->mArticle, &$sectionanchor, &$extraQuery )
                                );
@@ -1434,8 +1434,8 @@ class EditPage {
        protected function runPostMergeFilters( Content $content, Status $status, User $user ) {
                // Run old style post-section-merge edit filter
                if ( !ContentHandler::runLegacyHooks( 'EditFilterMerged',
-                       array( $this, $content, &$this->hookError, $this->summary ) ) ) {
-
+                       array( $this, $content, &$this->hookError, $this->summary ) )
+               ) {
                        # Error messages etc. could be handled within the hook...
                        $status->fatal( 'hookaborted' );
                        $status->value = self::AS_HOOK_ERROR;
@@ -1448,15 +1448,24 @@ class EditPage {
                }
 
                // Run new style post-section-merge edit filter
-               if ( !wfRunHooks( 'EditFilterMergedContent',
-                       array( $this->mArticle->getContext(), $content, $status, $this->summary,
-                               $user, $this->minoredit ) ) ) {
-
+               if ( !Hooks::run( 'EditFilterMergedContent',
+                               array( $this->mArticle->getContext(), $content, $status, $this->summary,
+                               $user, $this->minoredit ) )
+               ) {
                        # Error messages etc. could be handled within the hook...
-                       // XXX: $status->value may already be something informative...
-                       $this->hookError = $status->getWikiText();
-                       $status->fatal( 'hookaborted' );
-                       $status->value = self::AS_HOOK_ERROR;
+                       if ( $status->isGood() ) {
+                               $status->fatal( 'hookaborted' );
+                               // Not setting $this->hookError here is a hack to allow the hook
+                               // to cause a return to the edit page without $this->hookError
+                               // being set. This is used by ConfirmEdit to display a captcha
+                               // without any error message cruft.
+                       } else {
+                               $this->hookError = $status->getWikiText();
+                       }
+                       // Use the existing $status->value if the hook set it
+                       if ( !$status->value ) {
+                               $status->value = self::AS_HOOK_ERROR;
+                       }
                        return false;
                } elseif ( !$status->isOK() ) {
                        # ...or the hook could be expecting us to produce an error
@@ -1532,7 +1541,7 @@ class EditPage {
                wfProfileIn( __METHOD__ );
                wfProfileIn( __METHOD__ . '-checks' );
 
-               if ( !wfRunHooks( 'EditPage::attemptSave', array( $this ) ) ) {
+               if ( !Hooks::run( 'EditPage::attemptSave', array( $this ) ) ) {
                        wfDebug( "Hook 'EditPage::attemptSave' aborted article saving\n" );
                        $status->fatal( 'hookaborted' );
                        $status->value = self::AS_HOOK_ERROR;
@@ -1618,7 +1627,7 @@ class EditPage {
                        wfProfileOut( __METHOD__ );
                        return $status;
                }
-               if ( !wfRunHooks(
+               if ( !Hooks::run(
                        'EditFilter',
                        array( $this, $this->textbox1, $this->section, &$this->hookError, $this->summary ) )
                ) {
@@ -2345,6 +2354,9 @@ class EditPage {
         * Send the edit form and related headers to $wgOut
         * @param callable|null $formCallback That takes an OutputPage parameter; will be called
         *     during form output near the top, for captchas and the like.
+        *
+        * The $formCallback parameter is deprecated since MediaWiki 1.25. Please
+        * use the EditPage::showEditForm:fields hook instead.
         */
        function showEditForm( $formCallback = null ) {
                global $wgOut, $wgUser;
@@ -2360,7 +2372,7 @@ class EditPage {
                        $previewOutput = $this->getPreviewText();
                }
 
-               wfRunHooks( 'EditPage::showEditForm:initial', array( &$this, &$wgOut ) );
+               Hooks::run( 'EditPage::showEditForm:initial', array( &$this, &$wgOut ) );
 
                $this->setHeaders();
 
@@ -2403,6 +2415,7 @@ class EditPage {
                ) );
 
                if ( is_callable( $formCallback ) ) {
+                       wfWarn( 'The $formCallback parameter to ' . __METHOD__ . 'is deprecated' );
                        call_user_func_array( $formCallback, array( &$wgOut ) );
                }
 
@@ -2426,7 +2439,7 @@ class EditPage {
                        . Xml::closeElement( 'div' )
                );
 
-               wfRunHooks( 'EditPage::showEditForm:fields', array( &$this, &$wgOut ) );
+               Hooks::run( 'EditPage::showEditForm:fields', array( &$this, &$wgOut ) );
 
                // Put these up at the top to ensure they aren't lost on early form submission
                $this->showFormBeforeText();
@@ -3072,7 +3085,7 @@ HTML
                }
                # This hook seems slightly odd here, but makes things more
                # consistent for extensions.
-               wfRunHooks( 'OutputPageBeforeHTML', array( &$wgOut, &$text ) );
+               Hooks::run( 'OutputPageBeforeHTML', array( &$wgOut, &$text ) );
                $wgOut->addHTML( $text );
                if ( $this->mTitle->getNamespace() == NS_CATEGORY ) {
                        $this->mArticle->closeShowCategory();
@@ -3111,7 +3124,7 @@ HTML
 
                if ( $newContent ) {
                        ContentHandler::runLegacyHooks( 'EditPageGetDiffText', array( $this, &$newContent ) );
-                       wfRunHooks( 'EditPageGetDiffContent', array( $this, &$newContent ) );
+                       Hooks::run( 'EditPageGetDiffContent', array( $this, &$newContent ) );
 
                        $popts = ParserOptions::newFromUserAndLang( $wgUser, $wgContLang );
                        $newContent = $newContent->preSaveTransform( $this->mTitle, $wgUser, $popts );
@@ -3163,7 +3176,7 @@ HTML
         */
        protected function showTosSummary() {
                $msg = 'editpage-tos-summary';
-               wfRunHooks( 'EditPageTosSummary', array( $this->mTitle, &$msg ) );
+               Hooks::run( 'EditPageTosSummary', array( $this->mTitle, &$msg ) );
                if ( !wfMessage( $msg )->isDisabled() ) {
                        global $wgOut;
                        $wgOut->addHTML( '<div class="mw-tos-summary">' );
@@ -3207,7 +3220,7 @@ HTML
                                '[[' . wfMessage( 'copyrightpage' )->inContentLanguage()->text() . ']]' );
                }
                // Allow for site and per-namespace customization of contribution/copyright notice.
-               wfRunHooks( 'EditPageCopyrightWarning', array( $title, &$copywarnMsg ) );
+               Hooks::run( 'EditPageCopyrightWarning', array( $title, &$copywarnMsg ) );
 
                return "<div id=\"editpage-copywarn\">\n" .
                        call_user_func_array( 'wfMessage', $copywarnMsg )->$format() . "\n</div>";
@@ -3240,7 +3253,7 @@ HTML
                        Html::openElement( 'tbody' );
 
                foreach ( $output->getLimitReportData() as $key => $value ) {
-                       if ( wfRunHooks( 'ParserLimitReportFormat',
+                       if ( Hooks::run( 'ParserLimitReportFormat',
                                array( $key, &$value, &$limitReport, true, true )
                        ) ) {
                                $keyMsg = wfMessage( $key );
@@ -3308,7 +3321,7 @@ HTML
                $wgOut->addHTML( "      <span class='editHelp'>{$edithelp}</span>\n" );
                $wgOut->addHTML( "</div><!-- editButtons -->\n" );
 
-               wfRunHooks( 'EditPage::showStandardInputs:options', array( $this, $wgOut, &$tabindex ) );
+               Hooks::run( 'EditPage::showStandardInputs:options', array( $this, $wgOut, &$tabindex ) );
 
                $wgOut->addHTML( "</div><!-- editOptions -->\n" );
        }
@@ -3320,7 +3333,7 @@ HTML
        protected function showConflict() {
                global $wgOut;
 
-               if ( wfRunHooks( 'EditPageBeforeConflictDiff', array( &$this, &$wgOut ) ) ) {
+               if ( Hooks::run( 'EditPageBeforeConflictDiff', array( &$this, &$wgOut ) ) ) {
                        $wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourdiff" );
 
                        $content1 = $this->toEditContent( $this->textbox1 );
@@ -3471,7 +3484,7 @@ HTML
                        $content = $this->toEditContent( $this->textbox1 );
 
                        $previewHTML = '';
-                       if ( !wfRunHooks(
+                       if ( !Hooks::run(
                                'AlternateEditPreview',
                                array( $this, &$content, &$previewHTML, &$this->mParserOutput ) )
                        ) {
@@ -3496,7 +3509,6 @@ HTML
                        }
 
                        $parserOptions = $this->mArticle->makeParserOptions( $this->mArticle->getContext() );
-                       $parserOptions->setEditSection( false );
                        $parserOptions->setIsPreview( true );
                        $parserOptions->setIsSectionPreview( !is_null( $this->section ) && $this->section !== '' );
 
@@ -3541,20 +3553,24 @@ HTML
 
                        $hook_args = array( $this, &$content );
                        ContentHandler::runLegacyHooks( 'EditPageGetPreviewText', $hook_args );
-                       wfRunHooks( 'EditPageGetPreviewContent', $hook_args );
+                       Hooks::run( 'EditPageGetPreviewContent', $hook_args );
 
                        $parserOptions->enableLimitReport();
 
                        # For CSS/JS pages, we should have called the ShowRawCssJs hook here.
                        # But it's now deprecated, so never mind
 
-                       $content = $content->preSaveTransform( $this->mTitle, $wgUser, $parserOptions );
-                       $parserOutput = $content->getParserOutput(
-                               $this->getArticle()->getTitle(),
-                               null,
-                               $parserOptions
+                       $pstContent = $content->preSaveTransform( $this->mTitle, $wgUser, $parserOptions );
+                       $parserOutput = $pstContent->getParserOutput( $this->mTitle, null, $parserOptions );
+
+                       # Try to stash the edit for the final submission step
+                       # @todo: different date format preferences cause cache misses
+                       ApiStashEdit::stashEditFromPreview(
+                               $this->getArticle(), $content, $pstContent,
+                               $parserOutput, $parserOptions, $parserOptions, wfTimestampNow()
                        );
 
+                       $parserOutput->setEditSectionTokens( false ); // no section edit links
                        $previewHTML = $parserOutput->getText();
                        $this->mParserOutput = $parserOutput;
                        $wgOut->addParserOutputMetadata( $parserOutput );
@@ -3735,7 +3751,7 @@ HTML
 
                $toolbar = '<div id="toolbar"></div>';
 
-               wfRunHooks( 'EditPageBeforeEditToolbar', array( &$toolbar ) );
+               Hooks::run( 'EditPageBeforeEditToolbar', array( &$toolbar ) );
 
                return $toolbar;
        }
@@ -3802,7 +3818,7 @@ HTML
                                $checkboxes['watch'] = $watchThisHtml;
                        }
                }
-               wfRunHooks( 'EditPageBeforeEditChecks', array( &$this, &$checkboxes, &$tabindex ) );
+               Hooks::run( 'EditPageBeforeEditChecks', array( &$this, &$checkboxes, &$tabindex ) );
                return $checkboxes;
        }
 
@@ -3843,7 +3859,7 @@ HTML
                $buttons['diff'] = Html::submitButton( wfMessage( 'showdiff' )->text(),
                        $attribs );
 
-               wfRunHooks( 'EditPageBeforeEditButtons', array( &$this, &$buttons, &$tabindex ) );
+               Hooks::run( 'EditPageBeforeEditButtons', array( &$this, &$buttons, &$tabindex ) );
                return $buttons;
        }
 
@@ -3887,7 +3903,7 @@ HTML
                $wgOut->prepareErrorPage( wfMessage( 'nosuchsectiontitle' ) );
 
                $res = wfMessage( 'nosuchsectiontext', $this->section )->parseAsBlock();
-               wfRunHooks( 'EditPageNoSuchSection', array( &$this, &$res ) );
+               Hooks::run( 'EditPageNoSuchSection', array( &$this, &$res ) );
                $wgOut->addHTML( $res );
 
                $wgOut->returnToMain( false, $this->mTitle );
index 840e723..dd5cb0c 100644 (file)
@@ -348,7 +348,7 @@ class WikiExporter {
                                # Default JOIN, to be overridden...
                                $join['revision'] = array( 'INNER JOIN', 'page_id=rev_page AND page_latest=rev_id' );
                                # One, and only one hook should set this, and return false
-                               if ( wfRunHooks( 'WikiExporter::dumpStableQuery', array( &$tables, &$opts, &$join ) ) ) {
+                               if ( Hooks::run( 'WikiExporter::dumpStableQuery', array( &$tables, &$opts, &$join ) ) ) {
                                        wfProfileOut( __METHOD__ );
                                        throw new MWException( __METHOD__ . " given invalid history dump type." );
                                }
@@ -378,7 +378,7 @@ class WikiExporter {
 
                        $result = null; // Assuring $result is not undefined, if exception occurs early
                        try {
-                               wfRunHooks( 'ModifyExportQuery',
+                               Hooks::run( 'ModifyExportQuery',
                                                array( $this->db, &$tables, &$cond, &$opts, &$join ) );
 
                                # Do the query!
@@ -627,7 +627,7 @@ class XmlDumpWriter {
                                strval( $row->page_restrictions ) ) . "\n";
                }
 
-               wfRunHooks( 'XmlDumpWriterOpenPage', array( $this, &$out, $row, $title ) );
+               Hooks::run( 'XmlDumpWriterOpenPage', array( $this, &$out, $row, $title ) );
 
                return $out;
        }
@@ -722,7 +722,7 @@ class XmlDumpWriter {
                        $out .= "      <sha1/>\n";
                }
 
-               wfRunHooks( 'XmlDumpWriterWriteRevision', array( &$this, &$out, $row, $text ) );
+               Hooks::run( 'XmlDumpWriterWriteRevision', array( &$this, &$out, $row, $text ) );
 
                $out .= "    </revision>\n";
 
index b4e2458..1c709e6 100644 (file)
@@ -210,7 +210,7 @@ class FileDeleteForm {
                }
 
                if ( $status->isOK() ) {
-                       wfRunHooks( 'FileDeleteComplete', array( &$file, &$oldimage, &$page, &$user, &$reason ) );
+                       Hooks::run( 'FileDeleteComplete', array( &$file, &$oldimage, &$page, &$user, &$reason ) );
                }
 
                return $status;
index 7052820..fb298cf 100644 (file)
@@ -392,7 +392,7 @@ class GitInfo {
 
                if ( self::$viewers === false ) {
                        self::$viewers = $wgGitRepositoryViewers;
-                       wfRunHooks( 'GitViewers', array( &self::$viewers ) );
+                       Hooks::run( 'GitViewers', array( &self::$viewers ) );
                }
 
                return self::$viewers;
index 9cbf815..c1e1bb2 100644 (file)
@@ -3946,6 +3946,7 @@ function wfGetLangConverterCacheStorage() {
  * @param string|null $deprecatedVersion Optionally mark hook as deprecated with version number
  *
  * @return bool True if no handler aborted the hook
+ * @deprecated 1.25
  */
 function wfRunHooks( $event, array $args = array(), $deprecatedVersion = null ) {
        return Hooks::run( $event, $args, $deprecatedVersion );
index 4eb8e97..6f93351 100644 (file)
@@ -328,7 +328,7 @@ class WikiImporter {
         */
        public function finishImportPage( $title, $origTitle, $revCount, $sRevCount, $pageInfo ) {
                $args = func_get_args();
-               return wfRunHooks( 'AfterImportPage', $args );
+               return Hooks::run( 'AfterImportPage', $args );
        }
 
        /**
@@ -464,7 +464,7 @@ class WikiImporter {
                        $tag = $this->reader->name;
                        $type = $this->reader->nodeType;
 
-                       if ( !wfRunHooks( 'ImportHandleToplevelXMLTag', array( $this ) ) ) {
+                       if ( !Hooks::run( 'ImportHandleToplevelXMLTag', array( $this ) ) ) {
                                // Do nothing
                        } elseif ( $tag == 'mediawiki' && $type == XmlReader::END_ELEMENT ) {
                                break;
@@ -523,7 +523,7 @@ class WikiImporter {
 
                        $tag = $this->reader->name;
 
-                       if ( !wfRunHooks( 'ImportHandleLogItemXMLTag', array(
+                       if ( !Hooks::run( 'ImportHandleLogItemXMLTag', array(
                                $this, $logInfo
                        ) ) ) {
                                // Do nothing
@@ -590,7 +590,7 @@ class WikiImporter {
                        if ( $badTitle ) {
                                // The title is invalid, bail out of this page
                                $skip = true;
-                       } elseif ( !wfRunHooks( 'ImportHandlePageXMLTag', array( $this,
+                       } elseif ( !Hooks::run( 'ImportHandlePageXMLTag', array( $this,
                                                &$pageInfo ) ) ) {
                                // Do nothing
                        } elseif ( in_array( $tag, $normalFields ) ) {
@@ -652,7 +652,7 @@ class WikiImporter {
 
                        $tag = $this->reader->name;
 
-                       if ( !wfRunHooks( 'ImportHandleRevisionXMLTag', array(
+                       if ( !Hooks::run( 'ImportHandleRevisionXMLTag', array(
                                $this, $pageInfo, $revisionInfo
                        ) ) ) {
                                // Do nothing
@@ -744,7 +744,7 @@ class WikiImporter {
 
                        $tag = $this->reader->name;
 
-                       if ( !wfRunHooks( 'ImportHandleUploadXMLTag', array(
+                       if ( !Hooks::run( 'ImportHandleUploadXMLTag', array(
                                $this, $pageInfo
                        ) ) ) {
                                // Do nothing
index d84e5d0..bfb8937 100644 (file)
@@ -209,7 +209,7 @@ class Linker {
                $dummy = new DummyLinker; // dummy linker instance for bc on the hooks
 
                $ret = null;
-               if ( !wfRunHooks( 'LinkBegin',
+               if ( !Hooks::run( 'LinkBegin',
                        array( $dummy, $target, &$html, &$customAttribs, &$query, &$options, &$ret ) )
                ) {
                        wfProfileOut( __METHOD__ );
@@ -251,7 +251,7 @@ class Linker {
                }
 
                $ret = null;
-               if ( wfRunHooks( 'LinkEnd', array( $dummy, $target, $options, &$html, &$attribs, &$ret ) ) ) {
+               if ( Hooks::run( 'LinkEnd', array( $dummy, $target, $options, &$html, &$attribs, &$ret ) ) ) {
                        $ret = Html::rawElement( 'a', $attribs, $html );
                }
 
@@ -411,7 +411,7 @@ class Linker {
         */
        public static function makeSelfLinkObj( $nt, $html = '', $query = '', $trail = '', $prefix = '' ) {
                $ret = "<strong class=\"selflink\">{$prefix}{$html}</strong>{$trail}";
-               if ( !wfRunHooks( 'SelfLinkBegin', array( $nt, &$html, &$trail, &$prefix, &$ret ) ) ) {
+               if ( !Hooks::run( 'SelfLinkBegin', array( $nt, &$html, &$trail, &$prefix, &$ret ) ) ) {
                        return $ret;
                }
 
@@ -497,7 +497,7 @@ class Linker {
                        $alt = self::fnamePart( $url );
                }
                $img = '';
-               $success = wfRunHooks( 'LinkerMakeExternalImage', array( &$url, &$alt, &$img ) );
+               $success = Hooks::run( 'LinkerMakeExternalImage', array( &$url, &$alt, &$img ) );
                if ( !$success ) {
                        wfDebug( "Hook LinkerMakeExternalImage changed the output of external image "
                                . "with url {$url} and alt text {$alt} to {$img}\n", true );
@@ -551,7 +551,7 @@ class Linker {
        ) {
                $res = null;
                $dummy = new DummyLinker;
-               if ( !wfRunHooks( 'ImageBeforeProduceHTML', array( &$dummy, &$title,
+               if ( !Hooks::run( 'ImageBeforeProduceHTML', array( &$dummy, &$title,
                        &$file, &$frameParams, &$handlerParams, &$time, &$res ) ) ) {
                        return $res;
                }
@@ -1031,7 +1031,7 @@ class Linker {
                        'title' => $alt
                );
 
-               if ( !wfRunHooks( 'LinkerMakeMediaLinkFile',
+               if ( !Hooks::run( 'LinkerMakeMediaLinkFile',
                        array( $title, $file, &$html, &$attribs, &$ret ) ) ) {
                        wfDebug( "Hook LinkerMakeMediaLinkFile changed the output of link "
                                . "with url {$url} and text {$html} to {$ret}\n", true );
@@ -1090,7 +1090,7 @@ class Linker {
                }
                $attribs['rel'] = Parser::getExternalLinkRel( $url, $title );
                $link = '';
-               $success = wfRunHooks( 'LinkerMakeExternalLink',
+               $success = Hooks::run( 'LinkerMakeExternalLink',
                        array( &$url, &$text, &$link, &$attribs, $linktype ) );
                if ( !$success ) {
                        wfDebug( "Hook LinkerMakeExternalLink changed the output of link "
@@ -1176,7 +1176,7 @@ class Linker {
                        $items[] = self::emailLink( $userId, $userText );
                }
 
-               wfRunHooks( 'UserToolLinksEdit', array( $userId, $userText, &$items ) );
+               Hooks::run( 'UserToolLinksEdit', array( $userId, $userText, &$items ) );
 
                if ( $items ) {
                        return wfMessage( 'word-separator' )->plain()
@@ -1333,7 +1333,7 @@ class Linker {
                                $auto = $match[2];
                                $post = $match[3];
                                $comment = null;
-                               wfRunHooks( 'FormatAutocomments', array( &$comment, $pre, $auto, $post, $title, $local ) );
+                               Hooks::run( 'FormatAutocomments', array( &$comment, $pre, $auto, $post, $title, $local ) );
                                if ( $comment === null ) {
                                        $link = '';
                                        if ( $title ) {
index 392f558..bd68551 100644 (file)
@@ -72,7 +72,7 @@ class MWNamespace {
                /**
                 * @since 1.20
                 */
-               wfRunHooks( 'NamespaceIsMovable', array( $index, &$result ) );
+               Hooks::run( 'NamespaceIsMovable', array( $index, &$result ) );
 
                return $result;
        }
@@ -213,7 +213,7 @@ class MWNamespace {
                        if ( is_array( $wgExtraNamespaces ) ) {
                                $namespaces += $wgExtraNamespaces;
                        }
-                       wfRunHooks( 'CanonicalNamespaces', array( &$namespaces ) );
+                       Hooks::run( 'CanonicalNamespaces', array( &$namespaces ) );
                }
                return $namespaces;
        }
index 26f5e54..4b3d36a 100644 (file)
@@ -221,7 +221,7 @@ class MWTimestamp {
                $offsetRel = $relativeTo->offsetForUser( $user );
 
                $ts = '';
-               if ( wfRunHooks( 'GetHumanTimestamp', array( &$ts, $this, $relativeTo, $user, $lang ) ) ) {
+               if ( Hooks::run( 'GetHumanTimestamp', array( &$ts, $this, $relativeTo, $user, $lang ) ) ) {
                        $ts = $lang->getHumanTimestamp( $this, $relativeTo, $user );
                }
 
@@ -326,7 +326,7 @@ class MWTimestamp {
 
                $ts = '';
                $diff = $this->diff( $relativeTo );
-               if ( wfRunHooks(
+               if ( Hooks::run(
                        'GetRelativeTimestamp',
                        array( &$ts, &$diff, $this, $relativeTo, $user, $lang )
                ) ) {
index d281555..4b24a00 100644 (file)
@@ -273,7 +273,7 @@ class MagicWord {
        static function getVariableIDs() {
                if ( !self::$mVariableIDsInitialised ) {
                        # Get variable IDs
-                       wfRunHooks( 'MagicWordwgVariableIDs', array( &self::$mVariableIDs ) );
+                       Hooks::run( 'MagicWordwgVariableIDs', array( &self::$mVariableIDs ) );
                        self::$mVariableIDsInitialised = true;
                }
                return self::$mVariableIDs;
@@ -308,7 +308,7 @@ class MagicWord {
         */
        static function getDoubleUnderscoreArray() {
                if ( is_null( self::$mDoubleUnderscoreArray ) ) {
-                       wfRunHooks( 'GetDoubleUnderscoreIDs', array( &self::$mDoubleUnderscoreIDs ) );
+                       Hooks::run( 'GetDoubleUnderscoreIDs', array( &self::$mDoubleUnderscoreIDs ) );
                        self::$mDoubleUnderscoreArray = new MagicWordArray( self::$mDoubleUnderscoreIDs );
                }
                return self::$mDoubleUnderscoreArray;
index 7ce6d1b..6e2a0c9 100644 (file)
@@ -169,7 +169,7 @@ class MediaWiki {
                }
 
                $unused = null; // To pass it by reference
-               wfRunHooks( 'BeforeInitialize', array( &$title, &$unused, &$output, &$user, $request, $this ) );
+               Hooks::run( 'BeforeInitialize', array( &$title, &$unused, &$output, &$user, $request, $this ) );
 
                // Invalid titles. Bug 21776: The interwikis must redirect even if the page name is empty.
                if ( is_null( $title ) || ( $title->getDBkey() == '' && !$title->isExternal() )
@@ -233,7 +233,7 @@ class MediaWiki {
                        && ( $request->getVal( 'title' ) === null
                                || $title->getPrefixedDBkey() != $request->getVal( 'title' ) )
                        && !count( $request->getValueNames( array( 'action', 'title' ) ) )
-                       && wfRunHooks( 'TestCanonicalRedirect', array( $request, $title, $output ) )
+                       && Hooks::run( 'TestCanonicalRedirect', array( $request, $title, $output ) )
                ) {
                        if ( $title->isSpecialPage() ) {
                                list( $name, $subpage ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
@@ -342,7 +342,7 @@ class MediaWiki {
                        // Give extensions a change to ignore/handle redirects as needed
                        $ignoreRedirect = $target = false;
 
-                       wfRunHooks( 'InitializeArticleMaybeRedirect',
+                       Hooks::run( 'InitializeArticleMaybeRedirect',
                                array( &$title, &$request, &$ignoreRedirect, &$target, &$article ) );
 
                        // Follow redirects only for... redirects.
@@ -392,7 +392,7 @@ class MediaWiki {
                $title = $this->context->getTitle();
                $user = $this->context->getUser();
 
-               if ( !wfRunHooks( 'MediaWikiPerformAction',
+               if ( !Hooks::run( 'MediaWikiPerformAction',
                                array( $output, $page, $title, $user, $request, $this ) )
                ) {
                        wfProfileOut( __METHOD__ );
@@ -416,7 +416,7 @@ class MediaWiki {
                        return;
                }
 
-               if ( wfRunHooks( 'UnknownAction', array( $request->getVal( 'action', 'view' ), $page ) ) ) {
+               if ( Hooks::run( 'UnknownAction', array( $request->getVal( 'action', 'view' ), $page ) ) ) {
                        $output->setStatusCode( 404 );
                        $output->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
                }
@@ -530,7 +530,7 @@ class MediaWiki {
                        $redirUrl = preg_replace( '#^http://#', 'https://', $oldUrl );
 
                        // ATTENTION: This hook is likely to be removed soon due to overall design of the system.
-                       if ( wfRunHooks( 'BeforeHttpsRedirect', array( $this->context, &$redirUrl ) ) ) {
+                       if ( Hooks::run( 'BeforeHttpsRedirect', array( $this->context, &$redirUrl ) ) ) {
 
                                if ( $request->wasPosted() ) {
                                        // This is weird and we'd hope it almost never happens. This
index 3406831..d57f305 100644 (file)
@@ -200,7 +200,7 @@ class MimeMagic {
                global $IP;
 
                # Allow media handling extensions adding MIME-types and MIME-info
-               wfRunHooks( 'MimeMagicInit', array( $this ) );
+               Hooks::run( 'MimeMagicInit', array( $this ) );
 
                $types = MM_WELL_KNOWN_MIME_TYPES;
 
@@ -569,7 +569,7 @@ class MimeMagic {
                }
 
                # Media handling extensions can improve the MIME detected
-               wfRunHooks( 'MimeMagicImproveFromExtension', array( $this, $ext, &$mime ) );
+               Hooks::run( 'MimeMagicImproveFromExtension', array( $this, $ext, &$mime ) );
 
                if ( isset( $this->mMimeTypeAliases[$mime] ) ) {
                        $mime = $this->mMimeTypeAliases[$mime];
@@ -802,7 +802,7 @@ class MimeMagic {
                # people will hopefully nag and submit patches :)
                $mime = false;
                # Some strings by reference for performance - assuming well-behaved hooks
-               wfRunHooks(
+               Hooks::run(
                        'MimeMagicGuessFromContent',
                        array( $this, &$head, &$tail, $file, &$mime )
                );
index 994be91..065e189 100644 (file)
@@ -81,7 +81,7 @@ class MovePage {
                        }
                }
 
-               wfRunHooks( 'MovePageCheckPermissions',
+               Hooks::run( 'MovePageCheckPermissions',
                        array( $this->oldTitle, $this->newTitle, $user, $reason, $status )
                );
 
@@ -146,7 +146,7 @@ class MovePage {
                }
 
                // Hook for extensions to say a title can't be moved for technical reasons
-               wfRunHooks( 'MovePageIsValidMove', array( $this->oldTitle, $this->newTitle, $status ) );
+               Hooks::run( 'MovePageIsValidMove', array( $this->oldTitle, $this->newTitle, $status ) );
 
                return $status;
        }
@@ -231,7 +231,7 @@ class MovePage {
        public function move( User $user, $reason, $createRedirect ) {
                global $wgCategoryCollation;
 
-               wfRunHooks( 'TitleMove', array( $this->oldTitle, $this->newTitle, $user ) );
+               Hooks::run( 'TitleMove', array( $this->oldTitle, $this->newTitle, $user ) );
 
                // If it is a file, move it first.
                // It is done before all other moving stuff is done because it's hard to revert.
@@ -370,7 +370,7 @@ class MovePage {
 
                $dbw->commit( __METHOD__ );
 
-               wfRunHooks( 'TitleMoveComplete', array( &$this->oldTitle, &$this->newTitle, &$user, $pageid, $redirid, $reason ) );
+               Hooks::run( 'TitleMoveComplete', array( &$this->oldTitle, &$this->newTitle, &$user, $pageid, $redirid, $reason ) );
                return Status::newGood();
        }
 
@@ -486,7 +486,7 @@ class MovePage {
 
                $newpage->updateRevisionOn( $dbw, $nullRevision );
 
-               wfRunHooks( 'NewRevisionFromEditComplete',
+               Hooks::run( 'NewRevisionFromEditComplete',
                        array( $newpage, $nullRevision, $nullRevision->getParentId(), $user ) );
 
                $newpage->doEditUpdates( $nullRevision, $user,
@@ -513,7 +513,7 @@ class MovePage {
                                $redirectRevision->insertOn( $dbw );
                                $redirectArticle->updateRevisionOn( $dbw, $redirectRevision, 0 );
 
-                               wfRunHooks( 'NewRevisionFromEditComplete',
+                               Hooks::run( 'NewRevisionFromEditComplete',
                                        array( $redirectArticle, $redirectRevision, false, $user ) );
 
                                $redirectArticle->doEditUpdates( $redirectRevision, $user, array( 'created' => true ) );
index b0bbcdd..c6209ee 100644 (file)
@@ -129,7 +129,8 @@ function wfGzipHandler( $s ) {
        $headers = headers_list();
        $foundVary = false;
        foreach ( $headers as $header ) {
-               if ( substr( $header, 0, 5 ) == 'Vary:' ) {
+               $headerName = strtolower( substr( $header, 0, 5 ) );
+               if ( $headerName == 'vary:' ) {
                        $foundVary = true;
                        break;
                }
index 3294884..24b9e46 100644 (file)
@@ -786,7 +786,7 @@ class OutputPage extends ContextSource {
                        // bug 44570: the core page itself may not change, but resources might
                        $modifiedTimes['sepoch'] = wfTimestamp( TS_MW, time() - $config->get( 'SquidMaxage' ) );
                }
-               wfRunHooks( 'OutputPageCheckLastModified', array( &$modifiedTimes ) );
+               Hooks::run( 'OutputPageCheckLastModified', array( &$modifiedTimes ) );
 
                $maxModified = max( $modifiedTimes );
                $this->mLastModified = wfTimestamp( TS_RFC2822, $maxModified );
@@ -1325,7 +1325,7 @@ class OutputPage extends ContextSource {
                }
 
                # Add the remaining categories to the skin
-               if ( wfRunHooks(
+               if ( Hooks::run(
                        'OutputPageMakeCategoryLinks',
                        array( &$this, $categories, &$this->mCategoryLinks ) )
                ) {
@@ -1765,8 +1765,8 @@ class OutputPage extends ContextSource {
                // Link flags are ignored for now, but may in the future be
                // used to mark individual language links.
                $linkFlags = array();
-               wfRunHooks( 'LanguageLinks', array( $this->getTitle(), &$this->mLanguageLinks, &$linkFlags ) );
-               wfRunHooks( 'OutputPageParserOutput', array( &$this, $parserOutput ) );
+               Hooks::run( 'LanguageLinks', array( $this->getTitle(), &$this->mLanguageLinks, &$linkFlags ) );
+               Hooks::run( 'OutputPageParserOutput', array( &$this, $parserOutput ) );
        }
 
        /**
@@ -1795,7 +1795,7 @@ class OutputPage extends ContextSource {
         */
        public function addParserOutputText( $parserOutput ) {
                $text = $parserOutput->getText();
-               wfRunHooks( 'OutputPageBeforeHTML', array( &$this, &$text ) );
+               Hooks::run( 'OutputPageBeforeHTML', array( &$this, &$text ) );
                $this->addHTML( $text );
        }
 
@@ -1920,7 +1920,7 @@ class OutputPage extends ContextSource {
                                ),
                                $config->get( 'CacheVaryCookies' )
                        );
-                       wfRunHooks( 'GetCacheVaryCookies', array( $this, &$cookies ) );
+                       Hooks::run( 'GetCacheVaryCookies', array( $this, &$cookies ) );
                }
                return $cookies;
        }
@@ -2183,7 +2183,7 @@ class OutputPage extends ContextSource {
                        $redirect = $this->mRedirect;
                        $code = $this->mRedirectCode;
 
-                       if ( wfRunHooks( "BeforePageRedirect", array( $this, &$redirect, &$code ) ) ) {
+                       if ( Hooks::run( "BeforePageRedirect", array( $this, &$redirect, &$code ) ) ) {
                                if ( $code == '301' || $code == '303' ) {
                                        if ( !$config->get( 'DebugRedirects' ) ) {
                                                $message = HttpStatus::getMessage( $code );
@@ -2260,7 +2260,7 @@ class OutputPage extends ContextSource {
 
                        // Hook that allows last minute changes to the output page, e.g.
                        // adding of CSS or Javascript by extensions.
-                       wfRunHooks( 'BeforePageDisplay', array( &$this, &$sk ) );
+                       Hooks::run( 'BeforePageDisplay', array( &$this, &$sk ) );
 
                        wfProfileIn( 'Output-skin' );
                        $sk->outputPage();
@@ -2268,7 +2268,7 @@ class OutputPage extends ContextSource {
                }
 
                // This hook allows last minute changes to final overall output by modifying output buffer
-               wfRunHooks( 'AfterFinalPageOutput', array( $this ) );
+               Hooks::run( 'AfterFinalPageOutput', array( $this ) );
 
                $this->sendCacheControl();
 
@@ -2697,7 +2697,7 @@ class OutputPage extends ContextSource {
 
                // Allow skins and extensions to add body attributes they need
                $sk->addToBodyAttributes( $this, $bodyAttrs );
-               wfRunHooks( 'OutputPageBodyAttributes', array( $this, $sk, &$bodyAttrs ) );
+               Hooks::run( 'OutputPageBodyAttributes', array( $this, $sk, &$bodyAttrs ) );
 
                $ret .= Html::openElement( 'body', $bodyAttrs ) . "\n";
 
@@ -3247,7 +3247,7 @@ class OutputPage extends ContextSource {
                // Use the 'ResourceLoaderGetConfigVars' hook if the variable is not
                // page-dependant but site-wide (without state).
                // Alternatively, you may want to use OutputPage->addJsConfigVars() instead.
-               wfRunHooks( 'MakeGlobalVariablesScript', array( &$vars, $this ) );
+               Hooks::run( 'MakeGlobalVariablesScript', array( &$vars, $this ) );
 
                // Merge in variables from addJsConfigVars last
                return array_merge( $vars, $this->getJsConfigVars() );
index 93844f6..44995ac 100644 (file)
@@ -96,7 +96,7 @@ class Preferences {
                self::searchPreferences( $user, $context, $defaultPreferences );
                self::miscPreferences( $user, $context, $defaultPreferences );
 
-               wfRunHooks( 'GetPreferences', array( $user, &$defaultPreferences ) );
+               Hooks::run( 'GetPreferences', array( $user, &$defaultPreferences ) );
 
                self::loadPreferenceValues( $user, $context, $defaultPreferences );
                self::$defaultPreferences = $defaultPreferences;
@@ -1433,7 +1433,7 @@ class Preferences {
                                $user->setOption( $key, $value );
                        }
 
-                       wfRunHooks( 'PreferencesFormPreSave', array( $formData, $form, $user, &$result ) );
+                       Hooks::run( 'PreferencesFormPreSave', array( $formData, $form, $user, &$result ) );
                        $user->saveSettings();
                }
 
@@ -1575,7 +1575,7 @@ class PreferencesForm extends HTMLForm {
         */
        function getLegend( $key ) {
                $legend = parent::getLegend( $key );
-               wfRunHooks( 'PreferencesGetLegend', array( $this, $key, &$legend ) );
+               Hooks::run( 'PreferencesGetLegend', array( $this, $key, &$legend ) );
                return $legend;
        }
 }
index 4df6a9e..caa3ef5 100644 (file)
@@ -65,7 +65,7 @@ abstract class PrefixSearch {
                        $search = $title->getText();
                        if ( $ns[0] == NS_MAIN ) {
                                $ns = $namespaces; // no explicit prefix, use default namespaces
-                               wfRunHooks( 'PrefixSearchExtractNamespace', array( &$ns, &$search ) );
+                               Hooks::run( 'PrefixSearchExtractNamespace', array( &$ns, &$search ) );
                        }
                        return $this->searchBackend( $ns, $search, $limit, $offset );
                }
@@ -79,7 +79,7 @@ abstract class PrefixSearch {
                        $namespaces = array( $title->getNamespace() );
                        $search = '';
                } else {
-                       wfRunHooks( 'PrefixSearchExtractNamespace', array( &$namespaces, &$search ) );
+                       Hooks::run( 'PrefixSearchExtractNamespace', array( &$namespaces, &$search ) );
                }
 
                return $this->searchBackend( $namespaces, $search, $limit, $offset );
@@ -157,7 +157,7 @@ abstract class PrefixSearch {
                        }
                }
                $srchres = array();
-               if ( wfRunHooks( 'PrefixSearchBackend', array( $namespaces, $search, $limit, &$srchres, $offset ) ) ) {
+               if ( Hooks::run( 'PrefixSearchBackend', array( $namespaces, $search, $limit, &$srchres, $offset ) ) ) {
                        return $this->titles( $this->defaultSearchBackend( $namespaces, $search, $limit, $offset ) );
                }
                return $this->strings( $this->handleResultFromHook( $srchres, $namespaces, $search, $limit ) );
index 7bad8b5..76ad252 100644 (file)
@@ -321,7 +321,7 @@ class ProtectionForm {
                 *             you can also return an array of message name and its parameters
                 */
                $errorMsg = '';
-               if ( !wfRunHooks( 'ProtectionForm::save', array( $this->mArticle, &$errorMsg, $reasonstr ) ) ) {
+               if ( !Hooks::run( 'ProtectionForm::save', array( $this->mArticle, &$errorMsg, $reasonstr ) ) ) {
                        if ( $errorMsg == '' ) {
                                $errorMsg = array( 'hookaborted' );
                        }
@@ -452,7 +452,7 @@ class ProtectionForm {
                        "</td></tr>";
                }
                # Give extensions a chance to add items to the form
-               wfRunHooks( 'ProtectionForm::buildForm', array( $this->mArticle, &$out ) );
+               Hooks::run( 'ProtectionForm::buildForm', array( $this->mArticle, &$out ) );
 
                $out .= Xml::closeElement( 'tbody' ) . Xml::closeElement( 'table' );
 
@@ -623,6 +623,6 @@ class ProtectionForm {
                $out->addHTML( Xml::element( 'h2', null, $protectLogPage->getName()->text() ) );
                LogEventsList::showLogExtract( $out, 'protect', $this->mTitle );
                # Let extensions add other relevant log extracts
-               wfRunHooks( 'ProtectionForm::showLogExtract', array( $this->mArticle, $out ) );
+               Hooks::run( 'ProtectionForm::showLogExtract', array( $this->mArticle, $out ) );
        }
 }
index e81ed75..8ba79df 100644 (file)
@@ -1419,7 +1419,7 @@ class Revision implements IDBAccessObject {
 
                $this->mId = $rev_id !== null ? $rev_id : $dbw->insertId();
 
-               wfRunHooks( 'RevisionInsertComplete', array( &$this, $data, $flags ) );
+               Hooks::run( 'RevisionInsertComplete', array( &$this, $data, $flags ) );
 
                wfProfileOut( __METHOD__ );
                return $this->mId;
index 1654643..11c30a2 100644 (file)
@@ -1855,7 +1855,7 @@ class Sanitizer {
         */
        public static function validateEmail( $addr ) {
                $result = null;
-               if ( !wfRunHooks( 'isValidEmailAddr', array( $addr, &$result ) ) ) {
+               if ( !Hooks::run( 'isValidEmailAddr', array( $addr, &$result ) ) ) {
                        return $result;
                }
 
index f61de7e..535b13d 100644 (file)
@@ -584,7 +584,7 @@ wfDebugLog( 'caches', 'main: ' . get_class( $wgMemc ) .
 wfProfileOut( $fname . '-memcached' );
 
 // Most of the config is out, some might want to run hooks here.
-wfRunHooks( 'SetupAfterCache' );
+Hooks::run( 'SetupAfterCache' );
 
 wfProfileIn( $fname . '-session' );
 
@@ -634,7 +634,7 @@ $wgParser = new StubObject( 'wgParser', $wgParserConf['class'], array( $wgParser
 
 if ( !is_object( $wgAuth ) ) {
        $wgAuth = new AuthPlugin;
-       wfRunHooks( 'AuthPluginSetup', array( &$wgAuth ) );
+       Hooks::run( 'AuthPluginSetup', array( &$wgAuth ) );
 }
 
 /**
index 638da08..fa8d034 100644 (file)
@@ -747,7 +747,7 @@ class Title {
         * @param string $title The DB key form the title
         * @param string $fragment The link fragment (after the "#")
         * @param string $interwiki The interwiki prefix
-        * @param boolean $canoncialNamespace If true, use the canonical name for
+        * @param bool $canoncialNamespace If true, use the canonical name for
         *   $ns instead of the localized version.
         * @return string The prefixed form of the title
         */
@@ -1180,7 +1180,7 @@ class Title {
                }
 
                $result = true;
-               wfRunHooks( 'TitleIsMovable', array( $this, &$result ) );
+               Hooks::run( 'TitleIsMovable', array( $this, &$result ) );
                return $result;
        }
 
@@ -1252,7 +1252,7 @@ class Title {
                #   It's called here again to make sure hook functions can force this
                #   method to return true even outside the MediaWiki namespace.
 
-               wfRunHooks( 'TitleIsCssOrJsPage', array( $this, &$isCssOrJsPage ), '1.25' );
+               Hooks::run( 'TitleIsCssOrJsPage', array( $this, &$isCssOrJsPage ), '1.25' );
 
                return $isCssOrJsPage;
        }
@@ -1659,7 +1659,7 @@ class Title {
                # Finally, add the fragment.
                $url .= $this->getFragmentForURL();
 
-               wfRunHooks( 'GetFullURL', array( &$this, &$url, $query ) );
+               Hooks::run( 'GetFullURL', array( &$this, &$url, $query ) );
                return $url;
        }
 
@@ -1705,7 +1705,7 @@ class Title {
                        $dbkey = wfUrlencode( $this->getPrefixedDBkey() );
                        if ( $query == '' ) {
                                $url = str_replace( '$1', $dbkey, $wgArticlePath );
-                               wfRunHooks( 'GetLocalURL::Article', array( &$this, &$url ) );
+                               Hooks::run( 'GetLocalURL::Article', array( &$this, &$url ) );
                        } else {
                                global $wgVariantArticlePath, $wgActionPaths, $wgContLang;
                                $url = false;
@@ -1750,7 +1750,7 @@ class Title {
                                }
                        }
 
-                       wfRunHooks( 'GetLocalURL::Internal', array( &$this, &$url, $query ) );
+                       Hooks::run( 'GetLocalURL::Internal', array( &$this, &$url, $query ) );
 
                        // @todo FIXME: This causes breakage in various places when we
                        // actually expected a local URL and end up with dupe prefixes.
@@ -1758,7 +1758,7 @@ class Title {
                                $url = $wgServer . $url;
                        }
                }
-               wfRunHooks( 'GetLocalURL', array( &$this, &$url, $query ) );
+               Hooks::run( 'GetLocalURL', array( &$this, &$url, $query ) );
                return $url;
        }
 
@@ -1808,7 +1808,7 @@ class Title {
                $query = self::fixUrlQueryArgs( $query, $query2 );
                $server = $wgInternalServer !== false ? $wgInternalServer : $wgServer;
                $url = wfExpandUrl( $server . $this->getLocalURL( $query ), PROTO_HTTP );
-               wfRunHooks( 'GetInternalURL', array( &$this, &$url, $query ) );
+               Hooks::run( 'GetInternalURL', array( &$this, &$url, $query ) );
                return $url;
        }
 
@@ -1826,7 +1826,7 @@ class Title {
        public function getCanonicalURL( $query = '', $query2 = false ) {
                $query = self::fixUrlQueryArgs( $query, $query2 );
                $url = wfExpandUrl( $this->getLocalURL( $query ) . $this->getFragmentForURL(), PROTO_CANONICAL );
-               wfRunHooks( 'GetCanonicalURL', array( &$this, &$url, $query ) );
+               Hooks::run( 'GetCanonicalURL', array( &$this, &$url, $query ) );
                return $url;
        }
 
@@ -1945,7 +1945,7 @@ class Title {
        private function checkQuickPermissions( $action, $user, $errors,
                $doExpensiveQueries, $short
        ) {
-               if ( !wfRunHooks( 'TitleQuickPermissions',
+               if ( !Hooks::run( 'TitleQuickPermissions',
                        array( $this, $user, $action, &$errors, $doExpensiveQueries, $short ) )
                ) {
                        return $errors;
@@ -2045,18 +2045,18 @@ class Title {
        private function checkPermissionHooks( $action, $user, $errors, $doExpensiveQueries, $short ) {
                // Use getUserPermissionsErrors instead
                $result = '';
-               if ( !wfRunHooks( 'userCan', array( &$this, &$user, $action, &$result ) ) ) {
+               if ( !Hooks::run( 'userCan', array( &$this, &$user, $action, &$result ) ) ) {
                        return $result ? array() : array( array( 'badaccess-group0' ) );
                }
                // Check getUserPermissionsErrors hook
-               if ( !wfRunHooks( 'getUserPermissionsErrors', array( &$this, &$user, $action, &$result ) ) ) {
+               if ( !Hooks::run( 'getUserPermissionsErrors', array( &$this, &$user, $action, &$result ) ) ) {
                        $errors = $this->resultToError( $errors, $result );
                }
                // Check getUserPermissionsErrorsExpensive hook
                if (
                        $doExpensiveQueries
                        && !( $short && count( $errors ) > 0 )
-                       && !wfRunHooks( 'getUserPermissionsErrorsExpensive', array( &$this, &$user, $action, &$result ) )
+                       && !Hooks::run( 'getUserPermissionsErrorsExpensive', array( &$this, &$user, $action, &$result ) )
                ) {
                        $errors = $this->resultToError( $errors, $result );
                }
@@ -2389,7 +2389,7 @@ class Title {
 
                if ( !$whitelisted ) {
                        # If the title is not whitelisted, give extensions a chance to do so...
-                       wfRunHooks( 'TitleReadWhitelist', array( $this, $user, &$whitelisted ) );
+                       Hooks::run( 'TitleReadWhitelist', array( $this, $user, &$whitelisted ) );
                        if ( !$whitelisted ) {
                                $errors[] = $this->missingPermissionError( $action, $short );
                        }
@@ -2523,7 +2523,7 @@ class Title {
                        $types = array_diff( $types, array( 'upload' ) );
                }
 
-               wfRunHooks( 'TitleGetRestrictionTypes', array( $this, &$types ) );
+               Hooks::run( 'TitleGetRestrictionTypes', array( $this, &$types ) );
 
                wfDebug( __METHOD__ . ': applicable restrictions to [[' .
                        $this->getPrefixedText() . ']] are {' . implode( ',', $types ) . "}\n" );
@@ -3576,7 +3576,7 @@ class Title {
                        $urls[] = $this->getInternalUrl( 'action=raw&ctype=text/css' );
                }
 
-               wfRunHooks( 'TitleSquidURLs', array( $this, &$urls ) );
+               Hooks::run( 'TitleSquidURLs', array( $this, &$urls ) );
                return $urls;
        }
 
@@ -4247,7 +4247,7 @@ class Title {
         */
        public function exists() {
                $exists = $this->getArticleID() != 0;
-               wfRunHooks( 'TitleExists', array( $this, &$exists ) );
+               Hooks::run( 'TitleExists', array( $this, &$exists ) );
                return $exists;
        }
 
@@ -4280,7 +4280,7 @@ class Title {
                 * @param Title $title
                 * @param bool|null $isKnown
                 */
-               wfRunHooks( 'TitleIsAlwaysKnown', array( $this, &$isKnown ) );
+               Hooks::run( 'TitleIsAlwaysKnown', array( $this, &$isKnown ) );
 
                if ( !is_null( $isKnown ) ) {
                        return $isKnown;
@@ -4603,7 +4603,7 @@ class Title {
                // on the Title object passed in, and should probably
                // tell the users to run updateCollations.php --force
                // in order to re-sort existing category relations.
-               wfRunHooks( 'GetDefaultSortkey', array( $this, &$unprefixed ) );
+               Hooks::run( 'GetDefaultSortkey', array( $this, &$unprefixed ) );
                if ( $prefix !== '' ) {
                        # Separate with a line feed, so the unprefixed part is only used as
                        # a tiebreaker when two pages have the exact same prefix.
@@ -4724,7 +4724,7 @@ class Title {
                        }
                }
 
-               wfRunHooks( 'TitleGetEditNotices', array( $this, $oldid, &$notices ) );
+               Hooks::run( 'TitleGetEditNotices', array( $this, $oldid, &$notices ) );
                return $notices;
        }
 }
index b67d9f4..0fb5b1e 100644 (file)
@@ -37,7 +37,7 @@ abstract class TitleArray implements Iterator {
         */
        static function newFromResult( $res ) {
                $array = null;
-               if ( !wfRunHooks( 'TitleArrayFromResult', array( &$array, $res ) ) ) {
+               if ( !Hooks::run( 'TitleArrayFromResult', array( &$array, $res ) ) ) {
                        return null;
                }
                if ( $array === null ) {
index 3cbb052..bda825f 100644 (file)
@@ -350,7 +350,7 @@ class User implements IDBAccessObject {
                                        // Loading from session failed. Load defaults.
                                        $this->loadDefaults();
                                }
-                               wfRunHooks( 'UserLoadAfterLoadFromSession', array( $this ) );
+                               Hooks::run( 'UserLoadAfterLoadFromSession', array( $this ) );
                                break;
                        default:
                                wfProfileOut( __METHOD__ );
@@ -709,7 +709,7 @@ class User implements IDBAccessObject {
                static $reservedUsernames = false;
                if ( !$reservedUsernames ) {
                        $reservedUsernames = $wgReservedUsernames;
-                       wfRunHooks( 'UserGetReservedNames', array( &$reservedUsernames ) );
+                       Hooks::run( 'UserGetReservedNames', array( &$reservedUsernames ) );
                }
 
                // Certain names may be reserved for batch processes.
@@ -817,7 +817,7 @@ class User implements IDBAccessObject {
 
                $result = false; //init $result to false for the internal checks
 
-               if ( !wfRunHooks( 'isValidPassword', array( $password, &$result, $this ) ) ) {
+               if ( !Hooks::run( 'isValidPassword', array( $password, &$result, $this ) ) ) {
                        $status->error( $result );
                        return $status;
                }
@@ -879,7 +879,7 @@ class User implements IDBAccessObject {
                        );
                }
                // Give extensions a chance to force an expiration
-               wfRunHooks( 'ResetPasswordExpiration', array( $this, &$newExpire ) );
+               Hooks::run( 'ResetPasswordExpiration', array( $this, &$newExpire ) );
                $this->mPasswordExpires = $newExpire;
        }
 
@@ -1049,7 +1049,7 @@ class User implements IDBAccessObject {
                $this->mRegistration = wfTimestamp( TS_MW );
                $this->mGroups = array();
 
-               wfRunHooks( 'UserLoadDefaults', array( $this, $name ) );
+               Hooks::run( 'UserLoadDefaults', array( $this, $name ) );
 
                wfProfileOut( __METHOD__ );
        }
@@ -1088,7 +1088,7 @@ class User implements IDBAccessObject {
         */
        private function loadFromSession() {
                $result = null;
-               wfRunHooks( 'UserLoadFromSession', array( $this, &$result ) );
+               Hooks::run( 'UserLoadFromSession', array( $this, &$result ) );
                if ( $result !== null ) {
                        return $result;
                }
@@ -1190,7 +1190,7 @@ class User implements IDBAccessObject {
                                : array()
                );
 
-               wfRunHooks( 'UserLoadFromDatabase', array( $this, &$s ) );
+               Hooks::run( 'UserLoadFromDatabase', array( $this, &$s ) );
 
                if ( $s !== false ) {
                        // Initialise user table data
@@ -1456,7 +1456,7 @@ class User implements IDBAccessObject {
                }
                $defOpt['skin'] = Skin::normalizeKey( $wgDefaultSkin );
 
-               wfRunHooks( 'UserGetDefaultOptions', array( &$defOpt ) );
+               Hooks::run( 'UserGetDefaultOptions', array( &$defOpt ) );
 
                return $defOpt;
        }
@@ -1562,7 +1562,7 @@ class User implements IDBAccessObject {
                }
 
                // Extensions
-               wfRunHooks( 'GetBlockedStatus', array( &$this ) );
+               Hooks::run( 'GetBlockedStatus', array( &$this ) );
 
                wfProfileOut( __METHOD__ );
        }
@@ -1702,7 +1702,7 @@ class User implements IDBAccessObject {
        public function pingLimiter( $action = 'edit', $incrBy = 1 ) {
                // Call the 'PingLimiter' hook
                $result = false;
-               if ( !wfRunHooks( 'PingLimiter', array( &$this, $action, &$result, $incrBy ) ) ) {
+               if ( !Hooks::run( 'PingLimiter', array( &$this, $action, &$result, $incrBy ) ) ) {
                        return $result;
                }
 
@@ -1846,7 +1846,7 @@ class User implements IDBAccessObject {
                        wfDebug( __METHOD__ . ": self-talk page, ignoring any blocks\n" );
                }
 
-               wfRunHooks( 'UserIsBlockedFrom', array( $this, $title, &$blocked, &$allowUsertalk ) );
+               Hooks::run( 'UserIsBlockedFrom', array( $this, $title, &$blocked, &$allowUsertalk ) );
 
                wfProfileOut( __METHOD__ );
                return $blocked;
@@ -1898,7 +1898,7 @@ class User implements IDBAccessObject {
                        $ip = $this->getRequest()->getIP();
                }
                $blocked = false;
-               wfRunHooks( 'UserIsBlockedGlobally', array( &$this, $ip, &$blocked ) );
+               Hooks::run( 'UserIsBlockedGlobally', array( &$this, $ip, &$blocked ) );
                $this->mBlockedGlobally = (bool)$blocked;
                return $this->mBlockedGlobally;
        }
@@ -2058,7 +2058,7 @@ class User implements IDBAccessObject {
         */
        public function getNewMessageLinks() {
                $talks = array();
-               if ( !wfRunHooks( 'UserRetrieveNewTalks', array( &$this, &$talks ) ) ) {
+               if ( !Hooks::run( 'UserRetrieveNewTalks', array( &$this, &$talks ) ) ) {
                        return $talks;
                } elseif ( !$this->getNewtalk() ) {
                        return array();
@@ -2435,7 +2435,7 @@ class User implements IDBAccessObject {
         */
        public function getEmail() {
                $this->load();
-               wfRunHooks( 'UserGetEmail', array( $this, &$this->mEmail ) );
+               Hooks::run( 'UserGetEmail', array( $this, &$this->mEmail ) );
                return $this->mEmail;
        }
 
@@ -2445,7 +2445,7 @@ class User implements IDBAccessObject {
         */
        public function getEmailAuthenticationTimestamp() {
                $this->load();
-               wfRunHooks( 'UserGetEmailAuthenticationTimestamp', array( $this, &$this->mEmailAuthenticated ) );
+               Hooks::run( 'UserGetEmailAuthenticationTimestamp', array( $this, &$this->mEmailAuthenticated ) );
                return $this->mEmailAuthenticated;
        }
 
@@ -2460,7 +2460,7 @@ class User implements IDBAccessObject {
                }
                $this->invalidateEmail();
                $this->mEmail = $str;
-               wfRunHooks( 'UserSetEmail', array( $this, &$this->mEmail ) );
+               Hooks::run( 'UserSetEmail', array( $this, &$this->mEmail ) );
        }
 
        /**
@@ -2836,7 +2836,7 @@ class User implements IDBAccessObject {
                        }
                }
 
-               wfRunHooks( 'UserResetAllOptions', array( $this, &$newOptions, $this->mOptions, $resetKinds ) );
+               Hooks::run( 'UserResetAllOptions', array( $this, &$newOptions, $this->mOptions, $resetKinds ) );
 
                $this->mOptions = $newOptions;
                $this->mOptionsLoaded = true;
@@ -2872,7 +2872,7 @@ class User implements IDBAccessObject {
                        return false;
                } else {
                        $https = $this->getBoolOption( 'prefershttps' );
-                       wfRunHooks( 'UserRequiresHTTPS', array( $this, &$https ) );
+                       Hooks::run( 'UserRequiresHTTPS', array( $this, &$https ) );
                        if ( $https ) {
                                $https = wfCanIPUseHTTPS( $this->getRequest()->getIP() );
                        }
@@ -2903,7 +2903,7 @@ class User implements IDBAccessObject {
        public function getRights() {
                if ( is_null( $this->mRights ) ) {
                        $this->mRights = self::getGroupPermissions( $this->getEffectiveGroups() );
-                       wfRunHooks( 'UserGetRights', array( $this, &$this->mRights ) );
+                       Hooks::run( 'UserGetRights', array( $this, &$this->mRights ) );
                        // Force reindexation of rights when a hook has unset one of them
                        $this->mRights = array_values( array_unique( $this->mRights ) );
                }
@@ -2936,7 +2936,7 @@ class User implements IDBAccessObject {
                                $this->getAutomaticGroups( $recache ) // implicit groups
                        ) );
                        // Hook for additional groups
-                       wfRunHooks( 'UserEffectiveGroups', array( &$this, &$this->mEffectiveGroups ) );
+                       Hooks::run( 'UserEffectiveGroups', array( &$this, &$this->mEffectiveGroups ) );
                        // Force reindexation of groups when a hook has unset one of them
                        $this->mEffectiveGroups = array_values( array_unique( $this->mEffectiveGroups ) );
                        wfProfileOut( __METHOD__ );
@@ -3033,7 +3033,7 @@ class User implements IDBAccessObject {
         * @param string $group Name of the group to add
         */
        public function addGroup( $group ) {
-               if ( wfRunHooks( 'UserAddGroup', array( $this, &$group ) ) ) {
+               if ( Hooks::run( 'UserAddGroup', array( $this, &$group ) ) ) {
                        $dbw = wfGetDB( DB_MASTER );
                        if ( $this->getId() ) {
                                $dbw->insert( 'user_groups',
@@ -3066,7 +3066,7 @@ class User implements IDBAccessObject {
         */
        public function removeGroup( $group ) {
                $this->load();
-               if ( wfRunHooks( 'UserRemoveGroup', array( $this, &$group ) ) ) {
+               if ( Hooks::run( 'UserRemoveGroup', array( $this, &$group ) ) ) {
                        $dbw = wfGetDB( DB_MASTER );
                        $dbw->delete( 'user_groups',
                                array(
@@ -3290,7 +3290,7 @@ class User implements IDBAccessObject {
 
                // If we're working on user's talk page, we should update the talk page message indicator
                if ( $title->getNamespace() == NS_USER_TALK && $title->getText() == $this->getName() ) {
-                       if ( !wfRunHooks( 'UserClearNewTalkNotification', array( &$this, $oldid ) ) ) {
+                       if ( !Hooks::run( 'UserClearNewTalkNotification', array( &$this, $oldid ) ) ) {
                                return;
                        }
 
@@ -3435,7 +3435,7 @@ class User implements IDBAccessObject {
                        $cookies['Token'] = false;
                }
 
-               wfRunHooks( 'UserSetCookies', array( $this, &$session, &$cookies ) );
+               Hooks::run( 'UserSetCookies', array( $this, &$session, &$cookies ) );
 
                foreach ( $session as $name => $value ) {
                        $request->setSessionData( $name, $value );
@@ -3470,7 +3470,7 @@ class User implements IDBAccessObject {
         * Log this user out.
         */
        public function logout() {
-               if ( wfRunHooks( 'UserLogout', array( &$this ) ) ) {
+               if ( Hooks::run( 'UserLogout', array( &$this ) ) ) {
                        $this->doLogout();
                }
        }
@@ -3535,7 +3535,7 @@ class User implements IDBAccessObject {
 
                $this->saveOptions();
 
-               wfRunHooks( 'UserSaveSettings', array( $this ) );
+               Hooks::run( 'UserSaveSettings', array( $this ) );
                $this->clearSharedCache();
                $this->getUserPage()->invalidateCache();
        }
@@ -4133,7 +4133,7 @@ class User implements IDBAccessObject {
                // and fire the ConfirmEmailComplete hook on redundant confirmations.
                if ( !$this->isEmailConfirmed() ) {
                        $this->setEmailAuthenticationTimestamp( wfTimestampNow() );
-                       wfRunHooks( 'ConfirmEmailComplete', array( $this ) );
+                       Hooks::run( 'ConfirmEmailComplete', array( $this ) );
                }
                return true;
        }
@@ -4151,7 +4151,7 @@ class User implements IDBAccessObject {
                $this->mEmailTokenExpires = null;
                $this->setEmailAuthenticationTimestamp( null );
                $this->mEmail = '';
-               wfRunHooks( 'InvalidateEmailComplete', array( $this ) );
+               Hooks::run( 'InvalidateEmailComplete', array( $this ) );
                return true;
        }
 
@@ -4162,7 +4162,7 @@ class User implements IDBAccessObject {
        public function setEmailAuthenticationTimestamp( $timestamp ) {
                $this->load();
                $this->mEmailAuthenticated = $timestamp;
-               wfRunHooks( 'UserSetEmailAuthenticationTimestamp', array( $this, &$this->mEmailAuthenticated ) );
+               Hooks::run( 'UserSetEmailAuthenticationTimestamp', array( $this, &$this->mEmailAuthenticated ) );
        }
 
        /**
@@ -4176,7 +4176,7 @@ class User implements IDBAccessObject {
                        return false;
                }
                $canSend = $this->isEmailConfirmed();
-               wfRunHooks( 'UserCanSendEmail', array( &$this, &$canSend ) );
+               Hooks::run( 'UserCanSendEmail', array( &$this, &$canSend ) );
                return $canSend;
        }
 
@@ -4203,7 +4203,7 @@ class User implements IDBAccessObject {
                global $wgEmailAuthentication;
                $this->load();
                $confirmed = true;
-               if ( wfRunHooks( 'EmailConfirmed', array( &$this, &$confirmed ) ) ) {
+               if ( Hooks::run( 'EmailConfirmed', array( &$this, &$confirmed ) ) ) {
                        if ( $this->isAnon() ) {
                                return false;
                        }
@@ -4361,7 +4361,7 @@ class User implements IDBAccessObject {
                }
 
                // Allow extensions (e.g. OAuth) to say false
-               if ( !wfRunHooks( 'UserIsEveryoneAllowed', array( $right ) ) ) {
+               if ( !Hooks::run( 'UserIsEveryoneAllowed', array( $right ) ) ) {
                        $cache[$right] = false;
                        return false;
                }
@@ -4419,7 +4419,7 @@ class User implements IDBAccessObject {
                        } else {
                                self::$mAllRights = self::$mCoreRights;
                        }
-                       wfRunHooks( 'UserGetAllRights', array( &self::$mAllRights ) );
+                       Hooks::run( 'UserGetAllRights', array( &self::$mAllRights ) );
                }
                return self::$mAllRights;
        }
@@ -4433,7 +4433,7 @@ class User implements IDBAccessObject {
 
                $groups = $wgImplicitGroups;
                # Deprecated, use $wgImplicitGroups instead
-               wfRunHooks( 'UserGetImplicitGroups', array( &$groups ), '1.25' );
+               Hooks::run( 'UserGetImplicitGroups', array( &$groups ), '1.25' );
 
                return $groups;
        }
@@ -4867,7 +4867,7 @@ class User implements IDBAccessObject {
 
                $this->mOptionsLoaded = true;
 
-               wfRunHooks( 'UserLoadOptions', array( $this, &$this->mOptions ) );
+               Hooks::run( 'UserLoadOptions', array( $this, &$this->mOptions ) );
        }
 
        /**
@@ -4883,7 +4883,7 @@ class User implements IDBAccessObject {
 
                // Allow hooks to abort, for instance to save to a global profile.
                // Reset options to default state before saving.
-               if ( !wfRunHooks( 'UserSaveOptions', array( $this, &$saveOptions ) ) ) {
+               if ( !Hooks::run( 'UserSaveOptions', array( $this, &$saveOptions ) ) ) {
                        return;
                }
 
index 7da6582..e5621da 100644 (file)
@@ -27,7 +27,7 @@ abstract class UserArray implements Iterator {
         */
        static function newFromResult( $res ) {
                $userArray = null;
-               if ( !wfRunHooks( 'UserArrayFromResult', array( &$userArray, $res ) ) ) {
+               if ( !Hooks::run( 'UserArrayFromResult', array( &$userArray, $res ) ) ) {
                        return null;
                }
                if ( $userArray === null ) {
index bf99e95..e931f28 100644 (file)
@@ -138,7 +138,7 @@ class WebRequest {
                                        );
                                }
 
-                               wfRunHooks( 'WebRequestPathInfoRouter', array( $router ) );
+                               Hooks::run( 'WebRequestPathInfoRouter', array( $router ) );
 
                                $matches = $router->parse( $path );
                        }
@@ -1118,7 +1118,7 @@ HTML;
                }
 
                # Allow extensions to improve our guess
-               wfRunHooks( 'GetIP', array( &$ip ) );
+               Hooks::run( 'GetIP', array( &$ip ) );
 
                if ( !$ip ) {
                        throw new MWException( "Unable to determine IP." );
index d39f884..f977c20 100644 (file)
@@ -105,7 +105,7 @@ class WebResponse {
 
                $func = $options['raw'] ? 'setrawcookie' : 'setcookie';
 
-               if ( wfRunHooks( 'WebResponseSetCookie', array( &$name, &$value, &$expire, $options ) ) ) {
+               if ( Hooks::run( 'WebResponseSetCookie', array( &$name, &$value, &$expire, $options ) ) ) {
                        wfDebugLog( 'cookie',
                                $func . ': "' . implode( '", "',
                                        array(
index 159f711..c07ac73 100644 (file)
@@ -368,12 +368,10 @@ class Xml {
        public static function label( $label, $id, $attribs = array() ) {
                $a = array( 'for' => $id );
 
-               # FIXME avoid copy pasting below:
-               if ( isset( $attribs['class'] ) ) {
-                               $a['class'] = $attribs['class'];
-               }
-               if ( isset( $attribs['title'] ) ) {
-                               $a['title'] = $attribs['title'];
+               foreach ( array( 'class', 'title' ) as $attr ) {
+                       if ( isset( $attribs[$attr] ) ) {
+                               $a[$attr] = $attribs[$attr];
+                       }
                }
 
                return self::element( 'label', $a, $label );
index 8876724..6c8440a 100644 (file)
@@ -51,7 +51,7 @@ class EditAction extends FormlessAction {
                $page = $this->page;
                $user = $this->getUser();
 
-               if ( wfRunHooks( 'CustomEditor', array( $page, $user ) ) ) {
+               if ( Hooks::run( 'CustomEditor', array( $page, $user ) ) ) {
                        $editor = new EditPage( $page );
                        $editor->edit();
                }
index 4c9e85d..26f43cb 100644 (file)
@@ -63,7 +63,7 @@ abstract class FormAction extends Action {
                $this->fields = $this->getFormFields();
 
                // Give hooks a chance to alter the form, adding extra fields or text etc
-               wfRunHooks( 'ActionModifyFormFields', array( $this->getName(), &$this->fields, $this->page ) );
+               Hooks::run( 'ActionModifyFormFields', array( $this->getName(), &$this->fields, $this->page ) );
 
                $form = new HTMLForm( $this->fields, $this->getContext(), $this->getName() );
                $form->setSubmitCallback( array( $this, 'onSubmit' ) );
@@ -81,7 +81,7 @@ abstract class FormAction extends Action {
                $this->alterForm( $form );
 
                // Give hooks a chance to alter the form, adding extra fields or text etc
-               wfRunHooks( 'ActionBeforeFormDisplay', array( $this->getName(), &$form, $this->page ) );
+               Hooks::run( 'ActionBeforeFormDisplay', array( $this->getName(), &$form, $this->page ) );
 
                return $form;
        }
index 3be8aff..6ee5d2c 100644 (file)
@@ -204,7 +204,7 @@ class HistoryAction extends FormlessAction {
                        '</fieldset></form>'
                );
 
-               wfRunHooks( 'PageHistoryBeforeList', array( &$this->page, $this->getContext() ) );
+               Hooks::run( 'PageHistoryBeforeList', array( &$this->page, $this->getContext() ) );
 
                // Create and output the list.
                $pager = new HistoryPager( $this, $year, $month, $tagFilter, $conds );
@@ -420,7 +420,7 @@ class HistoryPager extends ReverseChronologicalPager {
                        $queryInfo['options'],
                        $this->tagFilter
                );
-               wfRunHooks( 'PageHistoryPager::getQueryInfo', array( &$this, &$queryInfo ) );
+               Hooks::run( 'PageHistoryPager::getQueryInfo', array( &$this, &$queryInfo ) );
 
                return $queryInfo;
        }
@@ -710,7 +710,7 @@ class HistoryPager extends ReverseChronologicalPager {
                        }
                }
                // Allow extension to add their own links here
-               wfRunHooks( 'HistoryRevisionTools', array( $rev, &$tools ) );
+               Hooks::run( 'HistoryRevisionTools', array( $rev, &$tools ) );
 
                if ( $tools ) {
                        $s2 .= ' ' . $this->msg( 'parentheses' )->rawParams( $lang->pipeList( $tools ) )->escaped();
@@ -728,7 +728,7 @@ class HistoryPager extends ReverseChronologicalPager {
                        $s .= ' <span class="mw-changeslist-separator">. .</span> ' . $s2;
                }
 
-               wfRunHooks( 'PageHistoryLineEnding', array( $this, &$row, &$s, &$classes ) );
+               Hooks::run( 'PageHistoryLineEnding', array( $this, &$row, &$s, &$classes ) );
 
                $attribs = array();
                if ( $classes ) {
index e7455f6..ad8e719 100644 (file)
@@ -114,7 +114,7 @@ class InfoAction extends FormlessAction {
                $pageInfo = $this->pageInfo();
 
                // Allow extensions to add additional information
-               wfRunHooks( 'InfoAction', array( $this->getContext(), &$pageInfo ) );
+               Hooks::run( 'InfoAction', array( $this->getContext(), &$pageInfo ) );
 
                // Render page information
                foreach ( $pageInfo as $header => $infoTable ) {
index d0d956e..727bed2 100644 (file)
@@ -117,7 +117,7 @@ class RawAction extends FormlessAction {
                        $response->header( 'HTTP/1.x 404 Not Found' );
                }
 
-               if ( !wfRunHooks( 'RawPageViewBeforeOutput', array( &$this, &$text ) ) ) {
+               if ( !Hooks::run( 'RawPageViewBeforeOutput', array( &$this, &$text ) ) ) {
                        wfDebug( __METHOD__ . ": RawPageViewBeforeOutput hook broke raw page output.\n" );
                }
 
index 8c9a46a..f333efb 100644 (file)
@@ -132,10 +132,10 @@ class WatchAction extends FormAction {
                $page = WikiPage::factory( $title );
 
                $status = Status::newFatal( 'hookaborted' );
-               if ( wfRunHooks( 'WatchArticle', array( &$user, &$page, &$status ) ) ) {
+               if ( Hooks::run( 'WatchArticle', array( &$user, &$page, &$status ) ) ) {
                        $status = Status::newGood();
                        $user->addWatch( $title, $checkRights );
-                       wfRunHooks( 'WatchArticleComplete', array( &$user, &$page ) );
+                       Hooks::run( 'WatchArticleComplete', array( &$user, &$page ) );
                }
 
                return $status;
@@ -156,10 +156,10 @@ class WatchAction extends FormAction {
                $page = WikiPage::factory( $title );
 
                $status = Status::newFatal( 'hookaborted' );
-               if ( wfRunHooks( 'UnwatchArticle', array( &$user, &$page, &$status ) ) ) {
+               if ( Hooks::run( 'UnwatchArticle', array( &$user, &$page, &$status ) ) ) {
                        $status = Status::newGood();
                        $user->removeWatch( $title );
-                       wfRunHooks( 'UnwatchArticleComplete', array( &$user, &$page ) );
+                       Hooks::run( 'UnwatchArticleComplete', array( &$user, &$page ) );
                }
 
                return $status;
index bbfe7cc..9cb895d 100644 (file)
@@ -1957,7 +1957,7 @@ abstract class ApiBase extends ContextSource {
         */
        public function getFinalDescription() {
                $desc = $this->getDescription();
-               wfRunHooks( 'APIGetDescription', array( &$this, &$desc ) );
+               Hooks::run( 'APIGetDescription', array( &$this, &$desc ) );
                $desc = self::escapeWikiText( $desc );
                if ( is_array( $desc ) ) {
                        $desc = join( "\n", $desc );
@@ -1975,7 +1975,7 @@ abstract class ApiBase extends ContextSource {
                }
                $msgs = array( $msg );
 
-               wfRunHooks( 'APIGetDescriptionMessages', array( $this, &$msgs ) );
+               Hooks::run( 'APIGetDescriptionMessages', array( $this, &$msgs ) );
 
                return $msgs;
        }
@@ -2005,7 +2005,7 @@ abstract class ApiBase extends ContextSource {
                        ) + ( isset( $params['token'] ) ? $params['token'] : array() );
                }
 
-               wfRunHooks( 'APIGetAllowedParams', array( &$this, &$params, $flags ) );
+               Hooks::run( 'APIGetAllowedParams', array( &$this, &$params, $flags ) );
 
                return $params;
        }
@@ -2019,7 +2019,7 @@ abstract class ApiBase extends ContextSource {
         */
        public function getFinalParamDescription() {
                $desc = $this->getParamDescription();
-               wfRunHooks( 'APIGetParamDescription', array( &$this, &$desc ) );
+               Hooks::run( 'APIGetParamDescription', array( &$this, &$desc ) );
 
                if ( !$desc ) {
                        $desc = array();
@@ -2087,7 +2087,7 @@ abstract class ApiBase extends ContextSource {
                        }
                }
 
-               wfRunHooks( 'APIGetParamDescriptionMessages', array( $this, &$msgs ) );
+               Hooks::run( 'APIGetParamDescriptionMessages', array( $this, &$msgs ) );
 
                return $msgs;
        }
index 89f8481..a7ba48a 100644 (file)
@@ -83,7 +83,7 @@ class ApiCreateAccount extends ApiBase {
 
                $loginForm = new LoginForm();
                $loginForm->setContext( $context );
-               wfRunHooks( 'AddNewAccountApiForm', array( $this, $loginForm ) );
+               Hooks::run( 'AddNewAccountApiForm', array( $this, $loginForm ) );
                $loginForm->load();
 
                $status = $loginForm->addNewaccountInternal();
@@ -113,7 +113,7 @@ class ApiCreateAccount extends ApiBase {
                        // Save settings (including confirmation token)
                        $user->saveSettings();
 
-                       wfRunHooks( 'AddNewAccount', array( $user, $params['mailpassword'] ) );
+                       Hooks::run( 'AddNewAccount', array( $user, $params['mailpassword'] ) );
 
                        if ( $params['mailpassword'] ) {
                                $logAction = 'byemail';
@@ -160,7 +160,7 @@ class ApiCreateAccount extends ApiBase {
                }
 
                // Give extensions a chance to modify the API result data
-               wfRunHooks( 'AddNewAccountApiResult', array( $this, $loginForm, &$result ) );
+               Hooks::run( 'AddNewAccountApiResult', array( $this, $loginForm, &$result ) );
 
                $apiResult->addValue( null, 'createaccount', $result );
        }
index c1598c8..f663cc6 100644 (file)
@@ -195,9 +195,9 @@ class ApiEditPage extends ApiBase {
                                        list( $params['undo'], $params['undoafter'] ) =
                                                array( $params['undoafter'], $params['undo'] );
                                }
-                               $undoafterRev = Revision::newFromID( $params['undoafter'] );
+                               $undoafterRev = Revision::newFromId( $params['undoafter'] );
                        }
-                       $undoRev = Revision::newFromID( $params['undo'] );
+                       $undoRev = Revision::newFromId( $params['undo'] );
                        if ( is_null( $undoRev ) || $undoRev->isDeleted( Revision::DELETED_TEXT ) ) {
                                $this->dieUsageMsg( array( 'nosuchrevid', $params['undo'] ) );
                        }
@@ -253,7 +253,8 @@ class ApiEditPage extends ApiBase {
                        'model' => $contentHandler->getModelID(),
                        'wpEditToken' => $params['token'],
                        'wpIgnoreBlankSummary' => '',
-                       'wpIgnoreBlankArticle' => true
+                       'wpIgnoreBlankArticle' => true,
+                       'wpIgnoreSelfRedirect' => true,
                );
 
                if ( !is_null( $params['summary'] ) ) {
@@ -381,7 +382,7 @@ class ApiEditPage extends ApiBase {
                // Run hooks
                // Handle APIEditBeforeSave parameters
                $r = array();
-               if ( !wfRunHooks( 'APIEditBeforeSave', array( $ep, $content, &$r ) ) ) {
+               if ( !Hooks::run( 'APIEditBeforeSave', array( $ep, $content, &$r ) ) ) {
                        if ( count( $r ) ) {
                                $r['result'] = 'Failure';
                                $apiResult->addValue( null, $this->getModuleName(), $r );
@@ -406,7 +407,14 @@ class ApiEditPage extends ApiBase {
                switch ( $status->value ) {
                        case EditPage::AS_HOOK_ERROR:
                        case EditPage::AS_HOOK_ERROR_EXPECTED:
-                               $this->dieUsageMsg( 'hookaborted' );
+                               if ( isset( $status->apiHookResult ) ) {
+                                       $r = $status->apiHookResult;
+                                       $r['result'] = 'Failure';
+                                       $apiResult->addValue( null, $this->getModuleName(), $r );
+                                       return;
+                               } else {
+                                       $this->dieUsageMsg( 'hookaborted' );
+                               }
 
                        case EditPage::AS_PARSE_ERROR:
                                $this->dieUsage( $status->getMessage(), 'parseerror' );
index 913b8eb..7bbd968 100644 (file)
@@ -172,7 +172,7 @@ abstract class ApiFormatBase extends ApiBase {
                                )
                        );
 
-                       if ( wfRunHooks( 'ApiFormatHighlight', array( $context, $result, $mime, $format ) ) ) {
+                       if ( Hooks::run( 'ApiFormatHighlight', array( $context, $result, $mime, $format ) ) ) {
                                $out->addHTML(
                                        Html::element( 'pre', array( 'class' => 'api-pretty-content' ), $result )
                                );
index 5d46a07..8708fb7 100644 (file)
@@ -609,7 +609,7 @@ class ApiHelp extends ApiBase {
 
                        $module->modifyHelp( $help, $options );
 
-                       wfRunHooks( 'APIHelpModifyOutput', array( $module, &$help, $options ) );
+                       Hooks::run( 'APIHelpModifyOutput', array( $module, &$help, $options ) );
 
                        $out .= join( "\n", $help );
                }
index cc4dee4..920dbbf 100644 (file)
@@ -92,7 +92,7 @@ class ApiLogin extends ApiBase {
                                // @todo FIXME: Split back and frontend from this hook.
                                // @todo FIXME: This hook should be placed in the backend
                                $injected_html = '';
-                               wfRunHooks( 'UserLoginComplete', array( &$user, &$injected_html ) );
+                               Hooks::run( 'UserLoginComplete', array( &$user, &$injected_html ) );
 
                                $result['result'] = 'Success';
                                $result['lguserid'] = intval( $user->getId() );
index bf81723..bf0ca9c 100644 (file)
@@ -39,7 +39,7 @@ class ApiLogout extends ApiBase {
 
                // Give extensions to do something after user logout
                $injected_html = '';
-               wfRunHooks( 'UserLogoutComplete', array( &$user, &$injected_html, $oldName ) );
+               Hooks::run( 'UserLogoutComplete', array( &$user, &$injected_html, $oldName ) );
        }
 
        public function isReadMode() {
index 3d04f95..81353f6 100644 (file)
@@ -192,7 +192,7 @@ class ApiMain extends ApiBase {
                if ( $uselang === 'user' ) {
                        $uselang = $this->getUser()->getOption( 'language' );
                        $uselang = RequestContext::sanitizeLangCode( $uselang );
-                       wfRunHooks( 'UserGetLanguageObject', array( $this->getUser(), &$uselang, $this ) );
+                       Hooks::run( 'UserGetLanguageObject', array( $this->getUser(), &$uselang, $this ) );
                } elseif ( $uselang === 'content' ) {
                        global $wgContLang;
                        $uselang = $wgContLang->getCode();
@@ -418,7 +418,7 @@ class ApiMain extends ApiBase {
                }
 
                // Allow extra cleanup and logging
-               wfRunHooks( 'ApiMain::onException', array( $this, $e ) );
+               Hooks::run( 'ApiMain::onException', array( $this, $e ) );
 
                // Log it
                if ( !( $e instanceof UsageException ) ) {
@@ -878,7 +878,7 @@ class ApiMain extends ApiBase {
 
                // Allow extensions to stop execution for arbitrary reasons.
                $message = false;
-               if ( !wfRunHooks( 'ApiCheckCanExecute', array( $module, $user, &$message ) ) ) {
+               if ( !Hooks::run( 'ApiCheckCanExecute', array( $module, $user, &$message ) ) ) {
                        $this->dieUsageMsg( $message );
                }
        }
@@ -952,7 +952,7 @@ class ApiMain extends ApiBase {
                // Execute
                $module->profileIn();
                $module->execute();
-               wfRunHooks( 'APIAfterExecute', array( &$module ) );
+               Hooks::run( 'APIAfterExecute', array( &$module ) );
                $module->profileOut();
 
                $this->reportUnusedParams();
index 2235ba9..f4b99ae 100644 (file)
@@ -96,7 +96,7 @@ class ApiOpenSearch extends ApiBase {
                        $this->search( $search, $limit, $namespaces, $resolveRedir, $results );
 
                        // Allow hooks to populate extracts and images
-                       wfRunHooks( 'ApiOpenSearchSuggest', array( &$results ) );
+                       Hooks::run( 'ApiOpenSearchSuggest', array( &$results ) );
 
                        // Trim extracts, if necessary
                        $length = $this->getConfig()->get( 'OpenSearchDescriptionLength' );
@@ -124,6 +124,9 @@ class ApiOpenSearch extends ApiBase {
                // Find matching titles as Title objects
                $searcher = new TitlePrefixSearch;
                $titles = $searcher->searchWithVariants( $search, $limit, $namespaces );
+               if ( !$titles ) {
+                       return;
+               }
 
                if ( $resolveRedir ) {
                        // Query for redirects
index 39cd6d9..1417ef7 100644 (file)
@@ -179,7 +179,7 @@ class ApiPageSet extends ApiBase {
 
                        if ( !$isDryRun ) {
                                $generator->executeGenerator( $this );
-                               wfRunHooks( 'APIQueryGeneratorAfterExecute', array( &$generator, &$this ) );
+                               Hooks::run( 'APIQueryGeneratorAfterExecute', array( &$generator, &$this ) );
                        } else {
                                // Prevent warnings from being reported on these parameters
                                $main = $this->getMain();
@@ -1213,7 +1213,7 @@ class ApiPageSet extends ApiBase {
         *
         * @param ApiResult|array &$result
         * @param array $path
-        * @return boolean Whether the data fit
+        * @return bool Whether the data fit
         */
        public function populateGeneratorData( &$result, array $path = array() ) {
                if ( $result instanceof ApiResult ) {
index 2bf1677..ff91b92 100644 (file)
@@ -87,7 +87,7 @@ class ApiParse extends ApiBase {
                if ( !is_null( $oldid ) || !is_null( $pageid ) || !is_null( $page ) ) {
                        if ( !is_null( $oldid ) ) {
                                // Don't use the parser cache
-                               $rev = Revision::newFromID( $oldid );
+                               $rev = Revision::newFromId( $oldid );
                                if ( !$rev ) {
                                        $this->dieUsage( "There is no revision ID $oldid", 'missingrev' );
                                }
@@ -267,7 +267,7 @@ class ApiParse extends ApiBase {
                                // Link flags are ignored for now, but may in the future be
                                // included in the result.
                                $linkFlags = array();
-                               wfRunHooks( 'LanguageLinks', array( $titleObj, &$langlinks, &$linkFlags ) );
+                               Hooks::run( 'LanguageLinks', array( $titleObj, &$langlinks, &$linkFlags ) );
                        }
                } else {
                        $langlinks = false;
index 3684461..779c418 100644 (file)
@@ -38,7 +38,7 @@ class ApiPatrol extends ApiBase {
                $this->requireOnlyOneParameter( $params, 'rcid', 'revid' );
 
                if ( isset( $params['rcid'] ) ) {
-                       $rc = RecentChange::newFromID( $params['rcid'] );
+                       $rc = RecentChange::newFromId( $params['rcid'] );
                        if ( !$rc ) {
                                $this->dieUsageMsg( array( 'nosuchrcid', $params['rcid'] ) );
                        }
index bd28408..514d559 100644 (file)
@@ -295,7 +295,7 @@ class ApiQuery extends ApiBase {
                                $cacheMode, $module->getCacheMode( $params ) );
                        $module->profileIn();
                        $module->execute();
-                       wfRunHooks( 'APIQueryAfterExecute', array( &$module ) );
+                       Hooks::run( 'APIQueryAfterExecute', array( &$module ) );
                        $module->profileOut();
                }
 
index 263ab0d..88b2074 100644 (file)
@@ -104,7 +104,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        'import' => array( 'ApiQueryInfo', 'getImportToken' ),
                        'watch' => array( 'ApiQueryInfo', 'getWatchToken' ),
                );
-               wfRunHooks( 'APIQueryInfoTokens', array( &$this->tokenFunctions ) );
+               Hooks::run( 'APIQueryInfoTokens', array( &$this->tokenFunctions ) );
 
                return $this->tokenFunctions;
        }
@@ -463,7 +463,7 @@ class ApiQueryInfo extends ApiQueryBase {
                                $pageInfo['preload'] = '';
                        } else {
                                $text = null;
-                               wfRunHooks( 'EditFormPreloadText', array( &$text, &$title ) );
+                               Hooks::run( 'EditFormPreloadText', array( &$text, &$title ) );
 
                                $pageInfo['preload'] = $text;
                        }
index e20380e..cdc61cd 100644 (file)
@@ -64,7 +64,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                $this->tokenFunctions = array(
                        'patrol' => array( 'ApiQueryRecentChanges', 'getPatrolToken' )
                );
-               wfRunHooks( 'APIQueryRecentChangesTokens', array( &$this->tokenFunctions ) );
+               Hooks::run( 'APIQueryRecentChangesTokens', array( &$this->tokenFunctions ) );
 
                return $this->tokenFunctions;
        }
index 32355b9..7092fc4 100644 (file)
@@ -61,7 +61,7 @@ class ApiQueryRevisions extends ApiQueryRevisionsBase {
                $this->tokenFunctions = array(
                        'rollback' => array( 'ApiQueryRevisions', 'getRollbackToken' )
                );
-               wfRunHooks( 'APIQueryRevisionsTokens', array( &$this->tokenFunctions ) );
+               Hooks::run( 'APIQueryRevisionsTokens', array( &$this->tokenFunctions ) );
 
                return $this->tokenFunctions;
        }
index 4d75a20..a658309 100644 (file)
@@ -78,7 +78,7 @@ abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
                        // DifferenceEngine returns a rather ambiguous empty
                        // string if that's not the case
                        if ( $params['diffto'] != 0 ) {
-                               $difftoRev = Revision::newFromID( $params['diffto'] );
+                               $difftoRev = Revision::newFromId( $params['diffto'] );
                                if ( !$difftoRev ) {
                                        $this->dieUsageMsg( array( 'nosuchrevid', $params['diffto'] ) );
                                }
index 3b8a514..f373021 100644 (file)
@@ -274,7 +274,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        $data['favicon'] = wfExpandUrl( $favicon, PROTO_RELATIVE );
                }
 
-               wfRunHooks( 'APIQuerySiteInfoGeneralInfo', array( $this, &$data ) );
+               Hooks::run( 'APIQuerySiteInfoGeneralInfo', array( $this, &$data ) );
 
                return $this->getResult()->addValue( 'query', $property, $data );
        }
@@ -490,7 +490,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                $data['admins'] = intval( SiteStats::numberingroup( 'sysop' ) );
                $data['jobs'] = intval( SiteStats::jobs() );
 
-               wfRunHooks( 'APIQuerySiteInfoStatisticsInfo', array( &$data ) );
+               Hooks::run( 'APIQuerySiteInfoStatisticsInfo', array( &$data ) );
 
                return $this->getResult()->addValue( 'query', $property, $data );
        }
index 279e8e3..e8d7258 100644 (file)
@@ -63,7 +63,7 @@ class ApiQueryTokens extends ApiQueryBase {
                                'rollback' => 'rollback',
                                'userrights' => 'userrights',
                        );
-                       wfRunHooks( 'ApiQueryTokensRegisterTypes', array( &$salts ) );
+                       Hooks::run( 'ApiQueryTokensRegisterTypes', array( &$salts ) );
                        ksort( $salts );
                        wfProfileOut( __METHOD__ );
                }
index db8cc1c..b7f2f9a 100644 (file)
@@ -75,7 +75,7 @@ class ApiQueryUsers extends ApiQueryBase {
                $this->tokenFunctions = array(
                        'userrights' => array( 'ApiQueryUsers', 'getUserrightsToken' ),
                );
-               wfRunHooks( 'APIQueryUsersTokens', array( &$this->tokenFunctions ) );
+               Hooks::run( 'APIQueryUsersTokens', array( &$this->tokenFunctions ) );
 
                return $this->tokenFunctions;
        }
index 91f3266..f28e610 100644 (file)
@@ -99,7 +99,7 @@ class ApiRsd extends ApiBase {
                                )
                        ),
                );
-               wfRunHooks( 'ApiRsdServiceApis', array( &$apis ) );
+               Hooks::run( 'ApiRsdServiceApis', array( &$apis ) );
 
                return $apis;
        }
index 00f6814..2f9f37e 100644 (file)
@@ -48,7 +48,8 @@ class ApiStashEdit extends ApiBase {
                        $this->dieUsage( "Unsupported content model/format", 'badmodelformat' );
                }
 
-               $text = trim( $params['text'] ); // needed so the key SHA1's match
+               // Trim and fix newlines so the key SHA1's match (see RequestContext::getText())
+               $text = rtrim( str_replace( "\r\n", "\n", $params['text'] ) );
                $textContent = ContentHandler::makeContent(
                        $text, $title, $params['contentmodel'], $params['contentformat'] );
 
@@ -107,27 +108,23 @@ class ApiStashEdit extends ApiBase {
                        $editInfo = false;
                        $status = 'ratelimited';
                } elseif ( $wgMemc->lock( $key, 0, 30 ) ) {
-                       $contentFormat = $content->getDefaultFormat();
-                       $editInfo = $page->prepareContentForEdit( $content, null, $user, $contentFormat );
-                       $wgMemc->unlock( $key );
+                       $format = $content->getDefaultFormat();
+                       $editInfo = $page->prepareContentForEdit( $content, null, $user, $format, false );
                        $status = 'error'; // default
+                       $unlocker = new ScopedCallback( function() use ( $key ) {
+                               global $wgMemc;
+                               $wgMemc->unlock( $key );
+                       } );
                } else {
                        $editInfo = false;
                        $status = 'busy';
                }
 
                if ( $editInfo && $editInfo->output ) {
-                       $parserOutput = $editInfo->output;
-                       // If an item is renewed, mind the cache TTL determined by config and parser functions
-                       $since = time() - wfTimestamp( TS_UNIX, $parserOutput->getTimestamp() );
-                       $ttl = min( $parserOutput->getCacheExpiry() - $since, 5 * 60 );
-                       if ( $ttl > 0 && !$parserOutput->getFlag( 'vary-revision' ) ) {
-                               // Only store what is actually needed
-                               $stashInfo = (object)array(
-                                       'pstContent' => $editInfo->pstContent,
-                                       'output' => $editInfo->output,
-                                       'timestamp' => $editInfo->timestamp
-                               );
+                       list( $stashInfo, $ttl ) = self::buildStashValue(
+                               $editInfo->pstContent, $editInfo->output, $editInfo->timestamp
+                       );
+                       if ( $stashInfo ) {
                                $ok = $wgMemc->set( $key, $stashInfo, $ttl );
                                if ( $ok ) {
                                        $status = 'stashed';
@@ -146,24 +143,69 @@ class ApiStashEdit extends ApiBase {
        }
 
        /**
-        * Get the temporary prepared edit stash key for a user
+        * Attempt to cache PST content and corresponding parser output in passing
         *
-        * @param Title $title
-        * @param Content $content
-        * @param User $user User to get parser options from
-        * @return string
+        * This method can be called when the output was already generated for other
+        * reasons. Parsing should not be done just to call this method, however.
+        * $pstOpts must be that of the user doing the edit preview. If $pOpts does
+        * not match the options of WikiPage::makeParserOptions( 'canonical' ), this
+        * will do nothing. Provided the values are cacheable, they will be stored
+        * in memcached so that final edit submission might make use of them.
+        *
+        * @param Article|WikiPage $page Page title
+        * @param Content $content Proposed page content
+        * @param Content $pstContent The result of preSaveTransform() on $content
+        * @param ParserOutput $pOut The result of getParserOutput() on $pstContent
+        * @param ParserOptions $pstOpts Options for $pstContent (MUST be for prospective author)
+        * @param ParserOptions $pOpts Options for $pOut
+        * @param string $timestamp TS_MW timestamp of parser output generation
+        * @return bool Success
         */
-       protected static function getStashKey(
-               Title $title, Content $content, User $user
+       public static function stashEditFromPreview(
+               Page $page, Content $content, Content $pstContent, ParserOutput $pOut,
+               ParserOptions $pstOpts, ParserOptions $pOpts, $timestamp
        ) {
-               return wfMemcKey( 'prepared-edit',
-                       md5( $title->getPrefixedDBkey() ), // handle rename races
-                       $content->getModel(),
-                       $content->getDefaultFormat(),
-                       sha1( $content->serialize( $content->getDefaultFormat() ) ),
-                       $user->getId() ?: md5( $user->getName() ), // account for user parser options
-                       $user->getId() ? $user->getTouched() : '-' // handle preference change races
-               );
+               global $wgMemc;
+
+               // getIsPreview() controls parser function behavior that references things
+               // like user/revision that don't exists yet. The user/text should already
+               // be set correctly by callers, just double check the preview flag.
+               if ( !$pOpts->getIsPreview() ) {
+                       return false; // sanity
+               } elseif ( $pOpts->getIsSectionPreview() ) {
+                       return false; // short-circuit (need the full content)
+               }
+
+               // PST parser options are for the user (handles signatures, etc...)
+               $user = $pstOpts->getUser();
+               // Get a key based on the source text, format, and user preferences
+               $key = self::getStashKey( $page->getTitle(), $content, $user );
+
+               // Parser output options must match cannonical options.
+               // Treat some options as matching that are different but don't matter.
+               $canonicalPOpts = $page->makeParserOptions( 'canonical' );
+               $canonicalPOpts->setIsPreview( true ); // force match
+               $canonicalPOpts->setTimestamp( $pOpts->getTimestamp() ); // force match
+               if ( !$pOpts->matches( $canonicalPOpts ) ) {
+                       wfDebugLog( 'StashEdit', "Uncacheable preview output for key '$key' (options)." );
+                       return false;
+               }
+
+               // Build a value to cache with a proper TTL
+               list( $stashInfo, $ttl ) = self::buildStashValue( $pstContent, $pOut, $timestamp );
+               if ( !$stashInfo ) {
+                       wfDebugLog( 'StashEdit', "Uncacheable parser output for key '$key' (rev/TTL)." );
+                       return false;
+               }
+
+               $ok = $wgMemc->set( $key, $stashInfo, $ttl );
+               if ( !$ok ) {
+                       wfDebugLog( 'StashEdit', "Failed to cache preview parser output for key '$key'." );
+               } else {
+                       wfDebugLog( 'StashEdit', "Cached preview output for key '$key'." );
+               }
+
+               return $ok;
        }
 
        /**
@@ -195,12 +237,13 @@ class ApiStashEdit extends ApiBase {
                        if ( $wgMemc->lock( $key, 30, 30 ) ) {
                                $editInfo = $wgMemc->get( $key );
                                $wgMemc->unlock( $key );
-                               $sec = microtime( true ) - $start;
-                               wfDebugLog( 'StashEdit', "Waited $sec seconds on '$key'." );
                        }
+                       $sec = microtime( true ) - $start;
+                       wfDebugLog( 'StashEdit', "Waited $sec seconds on '$key'." );
                }
 
                if ( !is_object( $editInfo ) || !$editInfo->output ) {
+                       wfDebugLog( 'StashEdit', "No cache value for key '$key'." );
                        return false;
                }
 
@@ -248,6 +291,59 @@ class ApiStashEdit extends ApiBase {
                return $editInfo;
        }
 
+       /**
+        * Get the temporary prepared edit stash key for a user
+        *
+        * This key can be used for caching prepared edits provided:
+        *   - a) The $user was used for PST options
+        *   - b) The parser output was made from the PST using cannonical matching options
+        *
+        * @param Title $title
+        * @param Content $content
+        * @param User $user User to get parser options from
+        * @return string
+        */
+       protected static function getStashKey( Title $title, Content $content, User $user ) {
+               $hash = sha1( implode( ':', array(
+                       $content->getModel(),
+                       $content->getDefaultFormat(),
+                       sha1( $content->serialize( $content->getDefaultFormat() ) ),
+                       $user->getId() ?: md5( $user->getName() ), // account for user parser options
+                       $user->getId() ? $user->getTouched() : '-' // handle preference change races
+               ) ) );
+
+               return wfMemcKey( 'prepared-edit', md5( $title->getPrefixedDBkey() ), $hash );
+       }
+
+       /**
+        * Build a value to store in memcached based on the PST content and parser output
+        *
+        * This makes a simple version of WikiPage::prepareContentForEdit() as stash info
+        *
+        * @param Content $pstContent
+        * @param ParserOutput $parserOutput
+        * @param string $timestamp TS_MW
+        * @return array (stash info array, TTL in seconds) or (null, 0)
+        */
+       protected static function buildStashValue(
+               Content $pstContent, ParserOutput $parserOutput, $timestamp
+       ) {
+               // If an item is renewed, mind the cache TTL determined by config and parser functions
+               $since = time() - wfTimestamp( TS_UNIX, $parserOutput->getTimestamp() );
+               $ttl = min( $parserOutput->getCacheExpiry() - $since, 5 * 60 );
+               if ( $ttl > 0 && !$parserOutput->getFlag( 'vary-revision' ) ) {
+                       // Only store what is actually needed
+                       $stashInfo = (object)array(
+                               'pstContent' => $pstContent,
+                               'output'     => $parserOutput,
+                               'timestamp'  => $timestamp
+                       );
+                       return array( $stashInfo, $ttl );
+               }
+
+               return array( null, 0 );
+       }
+
        public function getAllowedParams() {
                return array(
                        'title' => array(
index 2a60af9..f7290af 100644 (file)
@@ -70,7 +70,7 @@ class ApiTokens extends ApiBase {
                foreach ( $names as $name ) {
                        $types[$name] = array( 'ApiQueryInfo', 'get' . ucfirst( $name ) . 'Token' );
                }
-               wfRunHooks( 'ApiTokensGetTokenTypes', array( &$types ) );
+               Hooks::run( 'ApiTokensGetTokenTypes', array( &$types ) );
                ksort( $types );
                wfProfileOut( __METHOD__ );
 
index 943ae8e..c23e9ff 100644 (file)
@@ -69,7 +69,7 @@ class ApiUndelete extends ApiBase {
                }
 
                if ( $retval[1] ) {
-                       wfRunHooks( 'FileUndeleteComplete',
+                       Hooks::run( 'FileUndeleteComplete',
                                array( $titleObj, $params['fileids'], $this->getUser(), $params['reason'] ) );
                }
 
index 4a501c2..3f1d862 100644 (file)
@@ -23,5 +23,7 @@
        "apihelp-block-param-anononly": "Заблякаваць толькі ананімных удзельнікаў (напрыклад, забараніць ананімныя праўкі з гэтага IP-адрасу).",
        "apihelp-block-param-nocreate": "Забарона стварэньня рахункаў.",
        "apihelp-block-param-autoblock": "Аўтаматычна блякаваць апошні ўжыты IP-адрас, а таксама ўсе наступныя IP-адрасы, зь якіх будуць спробы ўваходу.",
-       "apihelp-block-param-noemail": "Забараняе ўдзельніку дасылаць лісты электроннай пошты празь вікі (трэба мець права «blockemail»)."
+       "apihelp-block-param-noemail": "Забараняе ўдзельніку дасылаць лісты электроннай пошты празь вікі (трэба мець права «blockemail»).",
+       "apihelp-block-param-hidename": "Схаваць імя ўдзельніка з журналу блякаваньняў (патрабуе права «hideuser»).",
+       "apihelp-block-param-allowusertalk": "Дазволіць удзельніку рэдагаваць уласную старонку гутарак (залежыць ад $wgBlockAllowsUTEdit)."
 }
diff --git a/includes/api/i18n/bs.json b/includes/api/i18n/bs.json
new file mode 100644 (file)
index 0000000..c8df203
--- /dev/null
@@ -0,0 +1,11 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Palapa"
+               ]
+       },
+       "apihelp-block-description": "Blokiraj korisnika",
+       "apihelp-block-param-reason": "Razlog za blokadu",
+       "apihelp-delete-description": "Obriši stranicu.",
+       "apihelp-edit-param-minor": "Mala izmjena."
+}
index 3c708a7..ff06724 100644 (file)
        "apihelp-block-param-nocreate": "Et Neu-Aanmelde verbeede",
        "apihelp-block-param-autoblock": "Dun automattesch de läzde <i lang=\"en\" xml:lang=\"en\">IP</i>-Adräß schpärre, di dä Metmaacher jehatt hät, un och all di <i lang=\"en\" xml:lang=\"en\">IP</i>-Adräße, vun wo dä versöhk, jet ze ändere.",
        "apihelp-block-param-watchuser": "Donn de Metmaachersigg un de Klaafsigg dohzoh op mig Oppaßleß säze.",
+       "apihelp-compare-description": "Donn de Ongerscheide zwesche zwai Sigge beschtemme.\n\nDo moß derför jeweils en Väsjohn, ene Tettel, odder ener Sigg iehr Kännong aanjävve, för de beide Sigge.",
+       "apihelp-compare-param-fromtitle": "Der Tettel vun dä eezte Sigg zom verjlihsche.",
+       "apihelp-compare-param-fromid": "De Kännong vun dä eezte Sigg zom verjlihsche.",
+       "apihelp-compare-param-fromrev": "De Väsjohn vun dä zwaite Sigg zom verjlihsche.",
+       "apihelp-compare-param-totitle": "Der Tettel vun dä zwaite Sigg zom verjlihsche.",
+       "apihelp-compare-param-toid": "De Kännong vun dä zwaite Sigg zom verjlihsche.",
+       "apihelp-compare-param-torev": "De Väsjohn vun dä zwaite Sigg zom verjlihsche.",
+       "apihelp-compare-example-1": "Fengk de Ongerscheide zwesche dä Väsjohne 1 un 2",
        "apihelp-createaccount-description": "Ene neue Zohjang för ene Metmaacher aanlähje.",
        "apihelp-createaccount-param-name": "Der Nahme för dä Metmaacher.",
        "apihelp-createaccount-param-password": "Et Paßwoot (Weed ävver it jebruc un övverjange, wann <code lang=\"en\" xml:lang=\"en\">$1mailpassword</code> jesaz es)",
+       "apihelp-createaccount-param-realname": "Dämm Medmaacher singe reschtejje Nahme - kann fott blihve.",
        "apihelp-delete-description": "Schmieß en Sigg fott.",
        "apihelp-delete-param-watch": "Donn die Sigg en Ding Oppassliss opnemme.",
        "apihelp-delete-param-unwatch": "Schmiiß di Sigg us Dinge Oppassless erus.",
diff --git a/includes/api/i18n/mg.json b/includes/api/i18n/mg.json
new file mode 100644 (file)
index 0000000..3126a28
--- /dev/null
@@ -0,0 +1,11 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Jagwar"
+               ]
+       },
+       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [https://www.mediawiki.org/wiki/API:Main_page Torohevitra be kokoa]\n* [https://www.mediawiki.org/wiki/API:FAQ Fanontaniana miverina matetika]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Lisitry ny mailaka manaraka]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Filazana API]\n* [https://bugzilla.wikimedia.org/buglist.cgi?component=API&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=bugs.delta_ts Baogy & hataka]\n</div>\n<strong>Status:</strong> \nTokony mandeha avokoa ny fitaovana aseho eto amin'ity pehy ity, na dia izany aza mbola am-panamboarana ny API ary mety hiova na oviana na oviana. Araho amin'ny alalan'ny fisoratana ny mailakao ao amin'ny [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ the mediawiki-api-announce lisitra fampielezana] ny fiovana.\n\n<strong>Hataka diso:</strong> \nRehefa alefa ao amin'i API ny hata, ho alefa miaraka amin'ny lakile \"MediaWiki-API-Error\" ny header HTTP ary samy homen-tsanda mitovy ny header ary ny kaodin-kadisoana. Ho an'ny torohay fanampiny dia jereo https://www.mediawiki.org/wiki/API:Errors_and_warnings.",
+       "apihelp-main-param-action": "Inona ny zavatra ho atao.",
+       "apihelp-main-param-format": "Format mivoaka",
+       "apihelp-createaccount-param-name": "Anaram-pikambana."
+}
index 73d4b64..9d6b027 100644 (file)
@@ -4,7 +4,7 @@
                        "Bjankuloski06"
                ]
        },
-       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [https://www.mediawiki.org/wiki/API:Main_page Ð\94окÑ\83менÑ\82аÑ\86иÑ\98а]\n* [https://www.mediawiki.org/wiki/API:FAQ Ð§Ð\9fÐ\9f]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Ð\9fоÑ\88Ñ\82енÑ\81ки Ñ\81пиÑ\81ок]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Ð¡Ð¾Ð¾Ð¿Ñ\88Ñ\82ениÑ\98а Ð·Ð° Ð\9fÑ\80илогоÑ\82]\n* [https://bugzilla.wikimedia.org/buglist.cgi?component=API&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=bugs.delta_ts Ð\93Ñ\80еÑ\88ки Ð¸ Ð±Ð°Ñ\80аÑ\9aа]\n</div>\n<strong>СÑ\82аÑ\82Ñ\83Ñ\81:</strong> Ð¡Ð¸Ñ\82е Ñ\81Ñ\82авки Ð½Ð° Ñ\81Ñ\82Ñ\80аниÑ\86ава Ð±Ð¸ Ñ\82Ñ\80ебало Ð´Ð° Ñ\80абоÑ\82аÑ\82, Ð½Ð¾ Ð\9fÑ\80илогоÑ\82 Ñ\81епак Ðµ Ð²Ð¾ Ð°ÐºÑ\82ивна Ñ\80азÑ\80абоÑ\82ка, Ñ\88Ñ\82о Ð·Ð½Ð°Ñ\87и Ð´ÐµÐºÐ° Ð¼Ð¾Ð¶Ðµ Ð´Ð° Ñ\81е Ñ\81мени Ð²Ð¾ Ñ\81екое Ð²Ñ\80еме. Ð\9eбÑ\98авиÑ\82е Ð·Ð° Ð¸Ð·Ð¼ÐµÐ½Ð¸ Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ð³Ð¸ Ð´Ð¾Ð·Ð½Ð°Ð²Ð°Ñ\82е Ð°ÐºÐ¾ Ñ\81е Ð¿Ñ\80иÑ\98авиÑ\82е Ð½Ð° [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ Ð¿Ð¾Ñ\88Ñ\82енÑ\81киоÑ\82 Ñ\81пиÑ\81ок â\80\9ethe mediawiki-api-announceâ\80\9c].\n\n<strong>Ð\9fогÑ\80еÑ\88ни Ð±Ð°Ñ\80аÑ\9aа:</strong> Ð\9aога Ð\9fÑ\80илогот ќе добие погрешни барања, ќе се испрати HTTP-заглавие со клучот „MediaWiki-API-Error“ и потоа на вредностите на заглавието и шифрата на грешката што ќе се појават ќе им биде зададена истата вредност. ПОвеќе информации ќе најдете на https://www.mediawiki.org/wiki/API:Errors_and_warnings.",
+       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [https://www.mediawiki.org/wiki/API:Main_page Ð\94окÑ\83менÑ\82аÑ\86иÑ\98а]\n* [https://www.mediawiki.org/wiki/API:FAQ Ð§Ð\9fÐ\9f]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Ð\9fоÑ\88Ñ\82енÑ\81ки Ñ\81пиÑ\81ок]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Ð¡Ð¾Ð¾Ð¿Ñ\88Ñ\82ениÑ\98а Ð·Ð° Ð\98звÑ\80Ñ\88никоÑ\82]\n* [https://bugzilla.wikimedia.org/buglist.cgi?component=API&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=bugs.delta_ts Ð\93Ñ\80еÑ\88ки Ð¸ Ð±Ð°Ñ\80аÑ\9aа]\n</div>\n<strong>СÑ\82аÑ\82Ñ\83Ñ\81:</strong> Ð¡Ð¸Ñ\82е Ñ\81Ñ\82авки Ð½Ð° Ñ\81Ñ\82Ñ\80аниÑ\86ава Ð±Ð¸ Ñ\82Ñ\80ебало Ð´Ð° Ñ\80абоÑ\82аÑ\82, Ð½Ð¾ Ð\98звÑ\80Ñ\88никоÑ\82 Ñ\81епак Ðµ Ð²Ð¾ Ð°ÐºÑ\82ивна Ñ\80азÑ\80абоÑ\82ка, Ñ\88Ñ\82о Ð·Ð½Ð°Ñ\87и Ð´ÐµÐºÐ° Ð¼Ð¾Ð¶Ðµ Ð´Ð° Ñ\81е Ñ\81мени Ð²Ð¾ Ñ\81екое Ð²Ñ\80еме. Ð\9eбÑ\98авиÑ\82е Ð·Ð° Ð¸Ð·Ð¼ÐµÐ½Ð¸ Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ð³Ð¸ Ð´Ð¾Ð·Ð½Ð°Ð²Ð°Ñ\82е Ð°ÐºÐ¾ Ñ\81е Ð¿Ñ\80иÑ\98авиÑ\82е Ð½Ð° [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ Ð¿Ð¾Ñ\88Ñ\82енÑ\81киоÑ\82 Ñ\81пиÑ\81ок â\80\9ethe mediawiki-api-announceâ\80\9c].\n\n<strong>Ð\9fогÑ\80еÑ\88ни Ð±Ð°Ñ\80аÑ\9aа:</strong> Ð\9aога Ð\98звÑ\80Ñ\88никот ќе добие погрешни барања, ќе се испрати HTTP-заглавие со клучот „MediaWiki-API-Error“ и потоа на вредностите на заглавието и шифрата на грешката што ќе се појават ќе им биде зададена истата вредност. ПОвеќе информации ќе најдете на https://www.mediawiki.org/wiki/API:Errors_and_warnings.",
        "apihelp-main-param-action": "Кое дејство да се изврши.",
        "apihelp-main-param-format": "Формат на изводот.",
        "apihelp-main-param-maxlag": "Максималниот заостаток може да се користи кога МедијаВики е воспоставен на грозд умножен од базата. За да спречите дополнителни заостатоци од дејства, овој параметар му наложува на клиентот да почека додека заостатокот не се намали под укажаната вредност. Во случај на преголем заостаток, системт ја дава грешката со код „maxlag“ со порака од обликот „Го чекам $host: има заостаток од $lag секунди“.<br />Погл. https://www.mediawiki.org/wiki/Manual:Maxlag_parameter за повеќе информации.",
        "apihelp-options-example-reset": "Врати ги сите поставки по основно",
        "apihelp-options-example-change": "Смени ги поставките „skinЗ“ и „hideminor“",
        "apihelp-options-example-complex": "Врати ги сите нагодувања по основно, а потоа задај ги „skin“ и „nickname“",
-       "apihelp-paraminfo-description": "Ð\9dабави Ð¸Ð½Ñ\84оÑ\80маÑ\86ии Ð·Ð° Ð¿Ñ\80илоÑ\88ки (API) модули.",
+       "apihelp-paraminfo-description": "Ð\9dабави Ð¸Ð½Ñ\84оÑ\80маÑ\86ии Ð·Ð° Ð¸Ð·Ð²Ñ\80Ñ\88ниÑ\87ки (API) модули.",
        "apihelp-paraminfo-param-modules": "Список на називи на модули (вредности на параметрите action= и format=, или пак „main“). Може да се укажат подмодули со „+“.",
        "apihelp-paraminfo-param-helpformat": "Формат на помошните низи.",
        "apihelp-paraminfo-param-querymodules": "Список на називи на модули за барања (вредност на параметарот prop=, meta= или list=). Користете го „$1modules=query+foo“ наместо „$1querymodules=foo“.",
        "apihelp-protect-param-reason": "Причиина за (од)заштитување",
        "apihelp-protect-example-protect": "Заштити страница",
        "apihelp-purge-param-forcelinkupdate": "Поднови ги табелите со врски.",
-       "apihelp-purge-example-simple": "Ð\9fÑ\80евÑ\87иÑ\82аÑ\98 Ð³Ð¸ â\80\9eÐ\93лавна Ñ\81Ñ\82Ñ\80аниÑ\86аâ\80\9c Ð¸ â\80\9eÐ\9fÑ\80илог“",
+       "apihelp-purge-example-simple": "Ð\9fÑ\80евÑ\87иÑ\82аÑ\98 Ð³Ð¸ â\80\9eÐ\93лавна Ñ\81Ñ\82Ñ\80аниÑ\86аâ\80\9c Ð¸ â\80\9eÐ\98звÑ\80Ñ\88ник“",
        "apihelp-query-param-list": "Кои списоци да се набават.",
        "apihelp-query-param-meta": "Кои метаподатоци да се набават.",
        "apihelp-query+allcategories-description": "Наброј ги сите категории.",
        "apihelp-xmlfm-description": "Давај го изводот во XML-формат (подобрен испис во HTML).",
        "apihelp-yaml-description": "Давај го изводот во YAML-формат.",
        "apihelp-yamlfm-description": "Давај го изводот во YAML-формат (подобрен испис во HTML).",
-       "api-format-title": "РезÑ\83лÑ\82аÑ\82 Ð¾Ð´ Ð\9fÑ\80илогот на МедијаВики",
-       "api-format-prettyprint-header": "Ја гледате HTML-претставата на форматот $1. HTML е добар за отстранување на грешки, но не е погоден за употреб во прилог.\n\nУкажете го параметарот за формат за да го смените изводниот формат. За да ги видите претставите на форматот $1 вон HTML, задајте format=$2.\n\nПовеќе информации ќе најдете на [https://www.mediawiki.org/wiki/API целосната документација], или пак [[Special:ApiHelp/main|помош со прилогот]].",
+       "api-format-title": "РезÑ\83лÑ\82аÑ\82 Ð¾Ð´ Ð\98звÑ\80Ñ\88никот на МедијаВики",
+       "api-format-prettyprint-header": "Ја гледате HTML-претставата на форматот $1. HTML е добар за отстранување на грешки, но не е погоден за употреба во извршник.\n\nУкажете го параметарот за формат за да го смените изводниот формат. За да ги видите претставите на форматот $1 вон HTML, задајте format=$2.\n\nПовеќе информации ќе најдете на [https://www.mediawiki.org/wiki/API целосната документација], или пак [[Special:ApiHelp/main|помош со извршникот]].",
        "api-orm-param-props": "Полиња за пребарување.",
        "api-orm-param-limit": "Макс. број на редови во изводот.",
        "api-pageset-param-titles": "Список на наслови на кои ќе се работи",
        "api-pageset-param-pageids": "Список на назнаки за страници на кои ќе се работи",
        "api-pageset-param-revids": "Список на назнаки на преработки на кои ќе се работи",
        "api-pageset-param-generator": "Дај го списокот на страници на кои ќе се работи исполнувајќи го укажаниот модул за барање.\n\n'''НАПОМЕНА:''' називите на создавачките параметри мора да ја имаат претставката „g“. Погледајте ги примерите.",
-       "api-help-title": "Ð\9fомоÑ\88 Ñ\81о Ð\9fÑ\80илогот на МедијаВики",
-       "api-help-lead": "Ð\9eва Ðµ Ñ\81амоÑ\81оздадена Ð´Ð¾ÐºÑ\83менÑ\82аÑ\86иÑ\81ка Ñ\81Ñ\82Ñ\80аниÑ\86а Ð·Ð° Ð\9fÑ\80илогоÑ\82 Ð½Ð° Ð\9cедиÑ\98аÐ\92ики.\n\nDocumentation and examples: https://www.mediawiki.org/wiki/API",
+       "api-help-title": "Ð\9fомоÑ\88 Ñ\81о Ð\98звÑ\80Ñ\88никот на МедијаВики",
+       "api-help-lead": "Ð\9eва Ðµ Ñ\81амоÑ\81оздадена Ð´Ð¾ÐºÑ\83менÑ\82аÑ\86иÑ\81ка Ñ\81Ñ\82Ñ\80аниÑ\86а Ð·Ð° Ð¸Ð·Ð²Ñ\80Ñ\88никоÑ\82 Ð½Ð° Ð\9cедиÑ\98аÐ\92ики.\n\nÐ\94окÑ\83менÑ\82аÑ\86иÑ\98а Ð¸ Ð¿Ñ\80имеÑ\80и: https://www.mediawiki.org/wiki/API",
        "api-help-main-header": "Главен модул",
        "api-help-flag-deprecated": "Овој модул е застарен.",
        "api-help-flag-internal": "<strong>Овој модул е внатрешен или нестабилен.</strong> Работењето може да му се промени без предупредување.",
        "api-help-permissions-granted-to": "{{PLURAL:$1|Доделена на}: $2",
        "api-help-right-apihighlimits": "Уоптреба на повисоки ограничувања за приложни барања (бавни барања: $1; брзи барања: $2). Ограничувањата за бавни барања важат и за повеќевредносни параметри.",
        "api-credits-header": "Признанија",
-       "api-credits": "РазÑ\80абоÑ\82Ñ\83ваÑ\87и Ð½Ð° Ð\9fÑ\80илогот:\n* Роан Катау (главен резработувач од септември 2007 до 2009 г.)\n* Виктор Василев\n* Брајан Тонг Мињ\n* Сем Рид\n* Јуриј Астрахан (создавач, главен разработувач од септември 2006 до септември 2007 г.)\n* Brad Jorsch (главен разработувач од 2013 г. до денес)\n\nВашите коментари, предлози и прашања испраќајте ги на mediawiki-api@lists.wikimedia.org\nа грешките пријавувајте ги на https://bugzilla.wikimedia.org/."
+       "api-credits": "РазÑ\80абоÑ\82Ñ\83ваÑ\87и Ð½Ð° Ð\98звÑ\80Ñ\88никот:\n* Роан Катау (главен резработувач од септември 2007 до 2009 г.)\n* Виктор Василев\n* Брајан Тонг Мињ\n* Сем Рид\n* Јуриј Астрахан (создавач, главен разработувач од септември 2006 до септември 2007 г.)\n* Brad Jorsch (главен разработувач од 2013 г. до денес)\n\nВашите коментари, предлози и прашања испраќајте ги на mediawiki-api@lists.wikimedia.org\nа грешките пријавувајте ги на https://bugzilla.wikimedia.org/."
 }
index 21db93a..450c641 100644 (file)
@@ -4,7 +4,8 @@
                        "Siebrand",
                        "Sjoerddebruin",
                        "Robin0van0der0vliet",
-                       "Mar(c)"
+                       "Mar(c)",
+                       "Valhallasw"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [https://www.mediawiki.org/wiki/API:Main_page Documentatie]\n* [https://www.mediawiki.org/wiki/API:FAQ FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api E-maillijst]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API-aankondigingen]\n* [https://bugzilla.wikimedia.org/buglist.cgi?component=API&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=bugs.delta_ts Bugs & verzoeken]\n</div>\n<strong>Status:</strong> Alle functies die op deze pagina worden weergegeven horen te werken. Aan de API wordt actief gewerkt, en deze kan gewijzigd worden. Abonneer u op  de [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ e-maillijst mediawiki-api-announce] voor meldingen over aanpassingen.\n\n<strong>Foutieve verzoeken:</strong> als de API foutieve verzoeken ontvangt, wordt er geantwoord met een HTTP-header met de sleutel \"MediaWiki-API-Error\" en daarna worden de waarde van de header en de foutcode op dezelfde waarde ingesteld. Zie https://www.mediawiki.org/wiki/API:Errors_and_warnings voor meer informatie.",
        "apihelp-main-param-maxlag": "De maximale vertraging kan gebruikt worden als MediaWiki is geïnstalleerd op een databasecluster die gebruik maakt van replicatie. Om te voorkomen dat handelingen nog meer databasereplicatievertraging veroorzaken, kan deze parameter er voor zorgen dat de client wacht totdat de replicatievertraging lager is dan de aangegeven waarde. In het geval van buitensporige vertraging, wordt de foutcode \"maxlag\" teruggegeven met een bericht als \"Waiting for $host: $lag seconds lagged\".<br />Zie https://www.mediawiki.org/wiki/Manual:Maxlag_parameter voor mee informatie.",
        "apihelp-main-param-smaxage": "Stelt de header \"s-maxage\" in op het aangegeven aantal seconden. Foutmeldingen komen nooit in de cache.",
        "apihelp-main-param-maxage": "Stelt de header \"max-age\" in op het aangegeven aantal seconden. Foutmeldingen komen nooit in de cache.",
+       "apihelp-main-param-assert": "Controleer of de gebruiker ingelogd is als \"user\" is meegegeven, en of de gebruiker het bot-gebruikersrecht heeft als \"bot\" is meegegeven.",
+       "apihelp-main-param-requestid": "Elke waarde die hier gegeven wordt wordt aan het antwoord toegevoegd. Dit kan gebruikt worden om verzoeken te onderscheiden.",
+       "apihelp-main-param-servedby": "Voeg de hostnaam van de server die de aanvraag heeft afgehandeld toe aan het antwoord.",
+       "apihelp-main-param-curtimestamp": "Voeg de huidige tijd toe aan het antwoord.",
        "apihelp-block-description": "Gebruiker blokkeren.",
        "apihelp-block-param-reason": "Reden voor blokkade.",
        "apihelp-edit-example-edit": "Pagina bewerken",
diff --git a/includes/api/i18n/te.json b/includes/api/i18n/te.json
new file mode 100644 (file)
index 0000000..8678f2a
--- /dev/null
@@ -0,0 +1,8 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Veeven"
+               ]
+       },
+       "apihelp-feedrecentchanges-example-simple": "ఇటీవలి మార్పులను చూడండి"
+}
index 3ce22d4..7c14404 100644 (file)
@@ -12,6 +12,7 @@
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [https://www.mediawiki.org/wiki/API:Main_page/zh 文档]\n* [https://www.mediawiki.org/wiki/API:FAQ/zh 常见问题]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api 邮件列表]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API公告]\n* [https://bugzilla.wikimedia.org/buglist.cgi?component=API&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=bugs.delta_ts 程序错误与功能请求]\n</div>\n<strong>状态信息:</strong> 本页所展示的所有特性都应正常工作,但是API仍在开发当中,将会随时变化。请订阅[https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ mediawiki-api-announce 邮件列表]以便获得更新通知。\n\n<strong>错误请求:</strong> 当API收到错误请求时,HTTP header将会返回一个包含\"MediaWiki-API-Error\"的值,随后header的值与error code将会送回并设置为相同的值。详细信息请参阅 https://www.mediawiki.org/wiki/API:Errors_and_warnings 。",
        "apihelp-main-param-action": "要执行的操作。",
        "apihelp-main-param-format": "输出的格式。",
+       "apihelp-main-param-assert": "如果设置为“user”就验证用户是否登录,或如果设置为“bot”就验证是否有机器人用户权限。",
        "apihelp-main-param-servedby": "包含保存结果请求的主机名。",
        "apihelp-main-param-curtimestamp": "在结果中包括当前时间戳。",
        "apihelp-main-param-origin": "当通过跨域名AJAX请求(CORS)访问API时,设置此作为起始域名。这必须包括在任何pre-flight请求中,并因此必须是请求的URI的一部分(而不是POST正文)。这必须匹配Origin中的一个起点:从头到底,因此它已经设置为像http://zh.wikipedia.org或https://meta.wikimedia.org的东西。如果此参数不匹配Origin: header,就返回403错误响应。如果此参数匹配Origin: header并且起点被白名单,将设置一个Access-Control-Allow-Origin开头。",
@@ -35,7 +36,7 @@
        "apihelp-compare-param-fromid": "要比较的第一个页面 ID。",
        "apihelp-compare-param-fromrev": "要比较的第一个修订版本。",
        "apihelp-compare-param-totitle": "要比较的第二个标题。",
-       "apihelp-compare-param-toid": "è¦\81æ¯\94è¾\83ç\9a\84第ä¸\80个页面 ID。",
+       "apihelp-compare-param-toid": "è¦\81æ¯\94è¾\83ç\9a\84第äº\8c个页面 ID。",
        "apihelp-compare-param-torev": "要比较的第二个修订版本。",
        "apihelp-compare-example-1": "在版本1和2中创建差异",
        "apihelp-createaccount-description": "创建一个新用户账户。",
        "apihelp-query+alldeletedrevisions-param-miser-user-namespace": "'''注意:'''由于[https://www.mediawiki.org/wiki/Manual:$wgMiserMode miser模式],同时使用$1user和$1namespace将导致继续前返回少于“$1limit”个结果,在极端条件下可能不返回任何结果。",
        "apihelp-query+alldeletedrevisions-example-user": "列出由User:Example作出的最近50次已删除贡献",
        "apihelp-query+alldeletedrevisions-example-ns-main": "列出最近50次已删除的主名字空间修订",
+       "apihelp-query+allfileusages-param-prefix": "搜索此值开头的所有文件标题。",
        "apihelp-query+allfileusages-param-limit": "要返回的总计项目。",
        "apihelp-query+allfileusages-param-dir": "罗列所采用的方向。",
        "apihelp-query+allfileusages-example-unique": "列出唯一性的文件标题",
        "apihelp-query+categorymembers-param-endsortkey": "请改用$1endhexsortkey。",
        "apihelp-query+categorymembers-example-simple": "获取[[:Category:Physics]]中的前10个页面。",
        "apihelp-query+categorymembers-example-generator": "获取关于[[:Category:Physics]]中的前10个页面的页面信息。",
+       "apihelp-query+contributors-description": "获取对一个页面的登录贡献者列表和匿名贡献数。",
+       "apihelp-query+contributors-param-limit": "返回的贡献数。",
        "apihelp-query+contributors-example-simple": "显示[[首页]]的贡献",
        "apihelp-query+deletedrevisions-example-titles": "列出[[首页]]和[[Talk:首页]]的已删除修订,包含内容",
        "apihelp-query+deletedrevs-paraminfo-modes": "{{PLURAL:$1|模式}}:$2",
        "apihelp-query+deletedrevs-param-from": "从此标题开始列出。",
        "apihelp-query+deletedrevs-param-to": "列出至此标题为止。",
+       "apihelp-query+deletedrevs-param-user": "只列出此用户做出的修订。",
+       "apihelp-query+deletedrevs-param-excludeuser": "不要列出此用户做出的修订。",
        "apihelp-query+deletedrevs-param-namespace": "只列出此名字空间的页面。",
        "apihelp-query+deletedrevs-example-mode1": "列出最近已删除的对首页和Talk:首页的贡献,带内容(模式1)",
        "apihelp-query+deletedrevs-example-mode2": "列出由Bob作出的最近50次已删除贡献(模式2)",
        "apihelp-query+links-example-simple": "从[[首页]]获取链接",
        "apihelp-query+links-example-generator": "获取有关[[首页]]链接页面的信息",
        "apihelp-query+links-example-namespaces": "获取用户和模板名字空间中来自[[首页]]的链接",
+       "apihelp-query+linkshere-param-namespace": "只包括这些名字空间的页面。",
        "apihelp-query+linkshere-param-limit": "返回多少。",
+       "apihelp-query+linkshere-param-show": "只显示符合以下标准的项:\n;redirect:只显示重定向。\n;!redirects:只显示非重定向。",
        "apihelp-query+linkshere-example-simple": "获取链接至[[首页]]的页面列表",
        "apihelp-query+linkshere-example-generator": "获取有关链接至[[首页]]的页面的信息",
        "apihelp-query+logevents-description": "从日志获取事件。",
index 05847db..1dedfdd 100644 (file)
@@ -67,7 +67,7 @@
        "apihelp-emailuser-param-text": "郵件內容。",
        "apihelp-emailuser-param-ccme": "寄送一份此郵件的複本給我。",
        "apihelp-emailuser-example-email": "寄送電子郵件給使用者 \"WikiSysop\" 使用內容 \"Content\"",
-       "apihelp-expandtemplates-description": "展開所有於 wikitext 中的樣板。",
+       "apihelp-expandtemplates-description": "展開所有於 wikitext 中板。",
        "apihelp-expandtemplates-param-title": "頁面標題。",
        "apihelp-expandtemplates-param-text": "要轉換的 Wikitext。",
        "apihelp-login-param-name": "使用者名稱。",
index ed62bba..753263c 100644 (file)
@@ -255,7 +255,7 @@ class BacklinkCache {
                        return $prefixes[$table];
                } else {
                        $prefix = null;
-                       wfRunHooks( 'BacklinkCacheGetPrefix', array( $table, &$prefix ) );
+                       Hooks::run( 'BacklinkCacheGetPrefix', array( $table, &$prefix ) );
                        if ( $prefix ) {
                                return $prefix;
                        } else {
@@ -303,7 +303,7 @@ class BacklinkCache {
                                break;
                        default:
                                $conds = null;
-                               wfRunHooks( 'BacklinkCacheGetConditions', array( $table, $this->title, &$conds ) );
+                               Hooks::run( 'BacklinkCacheGetConditions', array( $table, $this->title, &$conds ) );
                                if ( !$conds ) {
                                        throw new MWException( "Invalid table \"$table\" in " . __CLASS__ );
                                }
index 58ca2dc..c07032b 100644 (file)
@@ -131,7 +131,7 @@ class HTMLFileCache extends FileCacheBase {
                        return false;
                }
                // Allow extensions to disable caching
-               return wfRunHooks( 'HTMLFileCache::useFileCache', array( $context ) );
+               return Hooks::run( 'HTMLFileCache::useFileCache', array( $context ) );
        }
 
        /**
index c79d008..03162c0 100644 (file)
@@ -945,7 +945,7 @@ class LocalisationCache {
 
                        # Allow extensions an opportunity to adjust the data for this
                        # fallback
-                       wfRunHooks( 'LocalisationCacheRecacheFallback', array( $this, $csCode, &$csData ) );
+                       Hooks::run( 'LocalisationCacheRecacheFallback', array( $this, $csCode, &$csData ) );
 
                        # Merge the data for this fallback into the final array
                        if ( $csCode === $code ) {
@@ -1003,7 +1003,7 @@ class LocalisationCache {
                }
                # Run hooks
                $purgeBlobs = true;
-               wfRunHooks( 'LocalisationCacheRecache', array( $this, $code, &$allData, &$purgeBlobs ) );
+               Hooks::run( 'LocalisationCacheRecache', array( $this, $code, &$allData, &$purgeBlobs ) );
 
                if ( is_null( $allData['namespaceNames'] ) ) {
                        wfProfileOut( __METHOD__ );
index 43e00cd..532236e 100644 (file)
@@ -575,7 +575,7 @@ class MessageCache {
                global $wgContLang;
                MessageBlobStore::getInstance()->updateMessage( $wgContLang->lcfirst( $msg ) );
 
-               wfRunHooks( 'MessageCacheReplace', array( $title, $text ) );
+               Hooks::run( 'MessageCacheReplace', array( $title, $text ) );
 
                wfProfileOut( __METHOD__ );
        }
@@ -736,7 +736,7 @@ class MessageCache {
                        $lckey = $wgContLang->lcfirst( $lckey );
                }
 
-               wfRunHooks( 'MessageCache::get', array( &$lckey ) );
+               Hooks::run( 'MessageCache::get', array( &$lckey ) );
 
                if ( ord( $lckey ) < 128 ) {
                        $uckey = ucfirst( $lckey );
@@ -909,7 +909,7 @@ class MessageCache {
                } else {
                        // XXX: This is not cached in process cache, should it?
                        $message = false;
-                       wfRunHooks( 'MessagesPreLoad', array( $title, &$message ) );
+                       Hooks::run( 'MessagesPreLoad', array( $title, &$message ) );
                        if ( $message !== false ) {
                                return $message;
                        }
index 55da52c..6d26a2d 100644 (file)
@@ -40,7 +40,9 @@ class ResourceFileCache extends FileCacheBase {
        public static function newFromContext( ResourceLoaderContext $context ) {
                $cache = new self();
 
-               if ( $context->getOnly() === 'styles' ) {
+               if ( $context->getImage() ) {
+                       $cache->mType = 'image';
+               } elseif ( $context->getOnly() === 'styles' ) {
                        $cache->mType = 'css';
                } else {
                        $cache->mType = 'js';
@@ -69,7 +71,8 @@ class ResourceFileCache extends FileCacheBase {
                // Get all query values
                $queryVals = $context->getRequest()->getValues();
                foreach ( $queryVals as $query => $val ) {
-                       if ( $query === 'modules' || $query === 'version' || $query === '*' ) {
+                       if ( in_array( $query, array( 'modules', 'image', 'variant', 'version', '*' ) ) ) {
+                               // Use file cache regardless of the value of this parameter
                                continue; // note: &* added as IE fix
                        } elseif ( $query === 'skin' && $val === $wgDefaultSkin ) {
                                continue;
@@ -79,6 +82,8 @@ class ResourceFileCache extends FileCacheBase {
                                continue;
                        } elseif ( $query === 'debug' && $val === 'false' ) {
                                continue;
+                       } elseif ( $query === 'format' && $val === 'rasterized' ) {
+                               continue;
                        }
 
                        return false;
index 03d1289..932006d 100644 (file)
@@ -67,7 +67,7 @@ class ChangesList extends ContextSource {
                $user = $context->getUser();
                $sk = $context->getSkin();
                $list = null;
-               if ( wfRunHooks( 'FetchChangesList', array( $user, &$sk, &$list ) ) ) {
+               if ( Hooks::run( 'FetchChangesList', array( $user, &$sk, &$list ) ) ) {
                        $new = $context->getRequest()->getBool( 'enhanced', $user->getOption( 'usenewrc' ) );
 
                        return $new ? new EnhancedChangesList( $context ) : new OldChangesList( $context );
@@ -180,7 +180,7 @@ class ChangesList extends ContextSource {
         * @param ResultWrapper|array $rows
         */
        public function initChangesListRows( $rows ) {
-               wfRunHooks( 'ChangesListInitRows', array( $this, $rows ) );
+               Hooks::run( 'ChangesListInitRows', array( $this, $rows ) );
        }
 
        /**
@@ -364,7 +364,7 @@ class ChangesList extends ContextSource {
                # RTL/LTR marker
                $articlelink .= $this->getLanguage()->getDirMark();
 
-               wfRunHooks( 'ChangesListInsertArticleLink',
+               Hooks::run( 'ChangesListInsertArticleLink',
                        array( &$this, &$articlelink, &$s, &$rc, $unpatrolled, $watched ) );
 
                $s .= " $articlelink";
index 4eed926..5067886 100644 (file)
@@ -56,7 +56,7 @@ class OldChangesList extends ChangesList {
                                $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title'] );
                }
 
-               if ( !wfRunHooks( 'OldChangesListRecentChangesLine', array( &$this, &$html, $rc, &$classes ) ) ) {
+               if ( !Hooks::run( 'OldChangesListRecentChangesLine', array( &$this, &$html, $rc, &$classes ) ) ) {
                        wfProfileOut( __METHOD__ );
 
                        return false;
@@ -73,7 +73,7 @@ class OldChangesList extends ChangesList {
        /**
         * @param RecentChange $rc
         * @param string[] &$classes
-        * @param boolean $watched
+        * @param bool $watched
         *
         * @return string
         */
index d187c54..c719d8d 100644 (file)
@@ -257,7 +257,7 @@ class RecentChange {
        public function getPerformer() {
                if ( $this->mPerformer === false ) {
                        if ( $this->mAttribs['rc_user'] ) {
-                               $this->mPerformer = User::newFromID( $this->mAttribs['rc_user'] );
+                               $this->mPerformer = User::newFromId( $this->mAttribs['rc_user'] );
                        } else {
                                $this->mPerformer = User::newFromName( $this->mAttribs['rc_user_text'], false );
                        }
@@ -309,7 +309,7 @@ class RecentChange {
                $this->mAttribs['rc_id'] = $dbw->insertId();
 
                # Notify extensions
-               wfRunHooks( 'RecentChange_save', array( &$this ) );
+               Hooks::run( 'RecentChange_save', array( &$this ) );
 
                # Notify external application via UDP
                if ( !$noudp ) {
@@ -321,7 +321,7 @@ class RecentChange {
                        $editor = $this->getPerformer();
                        $title = $this->getTitle();
 
-                       if ( wfRunHooks( 'AbortEmailNotification', array( $editor, $title, $this ) ) ) {
+                       if ( Hooks::run( 'AbortEmailNotification', array( $editor, $title, $this ) ) ) {
                                # @todo FIXME: This would be better as an extension hook
                                $enotif = new EmailNotification();
                                $enotif->notifyOnPageChange( $editor, $title,
@@ -445,7 +445,7 @@ class RecentChange {
                // Automatic patrol needs "autopatrol", ordinary patrol needs "patrol"
                $right = $auto ? 'autopatrol' : 'patrol';
                $errors = array_merge( $errors, $this->getTitle()->getUserPermissionsErrors( $right, $user ) );
-               if ( !wfRunHooks( 'MarkPatrolled', array( $this->getAttribute( 'rc_id' ), &$user, false ) ) ) {
+               if ( !Hooks::run( 'MarkPatrolled', array( $this->getAttribute( 'rc_id' ), &$user, false ) ) ) {
                        $errors[] = array( 'hookaborted' );
                }
                // Users without the 'autopatrol' right can't patrol their
@@ -466,7 +466,7 @@ class RecentChange {
                $this->reallyMarkPatrolled();
                // Log this patrol event
                PatrolLog::record( $this, $auto, $user );
-               wfRunHooks( 'MarkPatrolledComplete', array( $this->getAttribute( 'rc_id' ), &$user, false ) );
+               Hooks::run( 'MarkPatrolledComplete', array( $this->getAttribute( 'rc_id' ), &$user, false ) );
 
                return array();
        }
index cb39fac..816572c 100644 (file)
@@ -446,7 +446,7 @@ abstract class AbstractContent implements Content {
                $lossy = ( $lossy === 'lossy' ); // string flag, convert to boolean for convenience
                $result = false;
 
-               wfRunHooks( 'ConvertContent', array( $this, $toModel, $lossy, &$result ) );
+               Hooks::run( 'ConvertContent', array( $this, $toModel, $lossy, &$result ) );
 
                return $result;
        }
@@ -480,7 +480,7 @@ abstract class AbstractContent implements Content {
 
                $po = new ParserOutput();
 
-               if ( wfRunHooks( 'ContentGetParserOutput',
+               if ( Hooks::run( 'ContentGetParserOutput',
                        array( $this, $title, $revId, $options, $generateHtml, &$po ) ) ) {
 
                        // Save and restore the old value, just in case something is reusing
@@ -491,7 +491,7 @@ abstract class AbstractContent implements Content {
                        $options->setRedirectTarget( $oldRedir );
                }
 
-               wfRunHooks( 'ContentAlterParserOutput', array( $this, $title, $po ) );
+               Hooks::run( 'ContentAlterParserOutput', array( $this, $title, $po ) );
 
                return $po;
        }
index 9aa42dd..8c806c6 100644 (file)
@@ -201,7 +201,7 @@ abstract class ContentHandler {
                $model = MWNamespace::getNamespaceContentModel( $ns );
 
                // Hook can determine default model
-               if ( !wfRunHooks( 'ContentHandlerDefaultModelFor', array( $title, &$model ) ) ) {
+               if ( !Hooks::run( 'ContentHandlerDefaultModelFor', array( $title, &$model ) ) ) {
                        if ( !is_null( $model ) ) {
                                return $model;
                        }
@@ -214,7 +214,7 @@ abstract class ContentHandler {
                }
 
                // Hook can force JS/CSS
-               wfRunHooks( 'TitleIsCssOrJsPage', array( $title, &$isCssOrJsPage ), '1.25' );
+               Hooks::run( 'TitleIsCssOrJsPage', array( $title, &$isCssOrJsPage ), '1.25' );
 
                // Is this a .css subpage of a user page?
                $isJsCssSubpage = NS_USER == $ns
@@ -229,7 +229,7 @@ abstract class ContentHandler {
                $isWikitext = $isWikitext && !$isCssOrJsPage && !$isJsCssSubpage;
 
                // Hook can override $isWikitext
-               wfRunHooks( 'TitleIsWikitextPage', array( $title, &$isWikitext ), '1.25' );
+               Hooks::run( 'TitleIsWikitextPage', array( $title, &$isWikitext ), '1.25' );
 
                if ( !$isWikitext ) {
                        switch ( $ext ) {
@@ -318,7 +318,7 @@ abstract class ContentHandler {
                if ( empty( $wgContentHandlers[$modelId] ) ) {
                        $handler = null;
 
-                       wfRunHooks( 'ContentHandlerForModelID', array( $modelId, &$handler ) );
+                       Hooks::run( 'ContentHandlerForModelID', array( $modelId, &$handler ) );
 
                        if ( $handler === null ) {
                                throw new MWException( "No handler for model '$modelId' registered in \$wgContentHandlers" );
@@ -660,7 +660,7 @@ abstract class ContentHandler {
                        $pageLang = wfGetLangObj( $lang );
                }
 
-               wfRunHooks( 'PageContentLanguage', array( $title, &$pageLang, $wgLang ) );
+               Hooks::run( 'PageContentLanguage', array( $title, &$pageLang, $wgLang ) );
 
                return wfGetLangObj( $pageLang );
        }
@@ -719,7 +719,7 @@ abstract class ContentHandler {
        public function canBeUsedOn( Title $title ) {
                $ok = true;
 
-               wfRunHooks( 'ContentModelCanBeUsedOn', array( $this->getModelID(), $title, &$ok ) );
+               Hooks::run( 'ContentModelCanBeUsedOn', array( $this->getModelID(), $title, &$ok ) );
 
                return $ok;
        }
@@ -1151,7 +1151,7 @@ abstract class ContentHandler {
                }
 
                // call the hook functions
-               $ok = wfRunHooks( $event, $args );
+               $ok = Hooks::run( $event, $args );
 
                // see if the hook changed the text
                foreach ( $contentTexts as $k => $orig ) {
index 9a8ab3a..7593d7c 100644 (file)
@@ -93,7 +93,7 @@ class WikitextContent extends TextContent {
                        # Inserting a new section
                        $subject = $sectionTitle ? wfMessage( 'newsectionheaderdefaultlevel' )
                                        ->rawParams( $sectionTitle )->inContentLanguage()->text() . "\n\n" : '';
-                       if ( wfRunHooks( 'PlaceNewSection', array( $this, $oldtext, $subject, &$text ) ) ) {
+                       if ( Hooks::run( 'PlaceNewSection', array( $this, $oldtext, $subject, &$text ) ) ) {
                                $text = strlen( trim( $oldtext ) ) > 0
                                        ? "{$oldtext}\n\n{$subject}{$text}"
                                        : "{$subject}{$text}";
index d620be9..2a610a3 100644 (file)
@@ -322,7 +322,7 @@ class RequestContext implements IContextSource {
                                $code = $request->getVal( 'uselang', $user->getOption( 'language' ) );
                                $code = self::sanitizeLangCode( $code );
 
-                               wfRunHooks( 'UserGetLanguageObject', array( $user, &$code, $this ) );
+                               Hooks::run( 'UserGetLanguageObject', array( $user, &$code, $this ) );
 
                                if ( $code === $this->getConfig()->get( 'LanguageCode' ) ) {
                                        $this->lang = $wgContLang;
@@ -362,7 +362,7 @@ class RequestContext implements IContextSource {
                        wfProfileIn( __METHOD__ . '-createskin' );
 
                        $skin = null;
-                       wfRunHooks( 'RequestContextCreateSkin', array( $this, &$skin ) );
+                       Hooks::run( 'RequestContextCreateSkin', array( $this, &$skin ) );
                        $factory = SkinFactory::getDefaultInstance();
 
                        // If the hook worked try to set a skin from it
index edce918..93ce61f 100644 (file)
@@ -46,10 +46,6 @@ abstract class DatabaseBase implements IDatabase {
        /** Maximum time to wait before retry */
        const DEADLOCK_DELAY_MAX = 1500000;
 
-# ------------------------------------------------------------------------------
-# Variables
-# ------------------------------------------------------------------------------
-
        protected $mLastQuery = '';
        protected $mDoneWrites = false;
        protected $mPHPError = false;
@@ -157,11 +153,6 @@ abstract class DatabaseBase implements IDatabase {
         */
        protected $allViews = null;
 
-# ------------------------------------------------------------------------------
-# Accessors
-# ------------------------------------------------------------------------------
-       # These optionally set a variable and return the previous state
-
        /**
         * A string describing the current software version, and possibly
         * other details in a user-friendly way. Will be listed on Special:Version, etc.
@@ -588,9 +579,167 @@ abstract class DatabaseBase implements IDatabase {
                return $this->getSqlFilePath( 'update-keys.sql' );
        }
 
-# ------------------------------------------------------------------------------
-# Other functions
-# ------------------------------------------------------------------------------
+       /**
+        * Get the type of the DBMS, as it appears in $wgDBtype.
+        *
+        * @return string
+        */
+       abstract function getType();
+
+       /**
+        * Open a connection to the database. Usually aborts on failure
+        *
+        * @param string $server Database server host
+        * @param string $user Database user name
+        * @param string $password Database user password
+        * @param string $dbName Database name
+        * @return bool
+        * @throws DBConnectionError
+        */
+       abstract function open( $server, $user, $password, $dbName );
+
+       /**
+        * Fetch the next row from the given result object, in object form.
+        * Fields can be retrieved with $row->fieldname, with fields acting like
+        * member variables.
+        * If no more rows are available, false is returned.
+        *
+        * @param ResultWrapper|stdClass $res Object as returned from DatabaseBase::query(), etc.
+        * @return stdClass|bool
+        * @throws DBUnexpectedError Thrown if the database returns an error
+        */
+       abstract function fetchObject( $res );
+
+       /**
+        * Fetch the next row from the given result object, in associative array
+        * form. Fields are retrieved with $row['fieldname'].
+        * If no more rows are available, false is returned.
+        *
+        * @param ResultWrapper $res Result object as returned from DatabaseBase::query(), etc.
+        * @return array|bool
+        * @throws DBUnexpectedError Thrown if the database returns an error
+        */
+       abstract function fetchRow( $res );
+
+       /**
+        * Get the number of rows in a result object
+        *
+        * @param mixed $res A SQL result
+        * @return int
+        */
+       abstract function numRows( $res );
+
+       /**
+        * Get the number of fields in a result object
+        * @see http://www.php.net/mysql_num_fields
+        *
+        * @param mixed $res A SQL result
+        * @return int
+        */
+       abstract function numFields( $res );
+
+       /**
+        * Get a field name in a result object
+        * @see http://www.php.net/mysql_field_name
+        *
+        * @param mixed $res A SQL result
+        * @param int $n
+        * @return string
+        */
+       abstract function fieldName( $res, $n );
+
+       /**
+        * Get the inserted value of an auto-increment row
+        *
+        * The value inserted should be fetched from nextSequenceValue()
+        *
+        * Example:
+        * $id = $dbw->nextSequenceValue( 'page_page_id_seq' );
+        * $dbw->insert( 'page', array( 'page_id' => $id ) );
+        * $id = $dbw->insertId();
+        *
+        * @return int
+        */
+       abstract function insertId();
+
+       /**
+        * Change the position of the cursor in a result object
+        * @see http://www.php.net/mysql_data_seek
+        *
+        * @param mixed $res A SQL result
+        * @param int $row
+        */
+       abstract function dataSeek( $res, $row );
+
+       /**
+        * Get the last error number
+        * @see http://www.php.net/mysql_errno
+        *
+        * @return int
+        */
+       abstract function lastErrno();
+
+       /**
+        * Get a description of the last error
+        * @see http://www.php.net/mysql_error
+        *
+        * @return string
+        */
+       abstract function lastError();
+
+       /**
+        * mysql_fetch_field() wrapper
+        * Returns false if the field doesn't exist
+        *
+        * @param string $table Table name
+        * @param string $field Field name
+        *
+        * @return Field
+        */
+       abstract function fieldInfo( $table, $field );
+
+       /**
+        * Get information about an index into an object
+        * @param string $table Table name
+        * @param string $index Index name
+        * @param string $fname Calling function name
+        * @return mixed Database-specific index description class or false if the index does not exist
+        */
+       abstract function indexInfo( $table, $index, $fname = __METHOD__ );
+
+       /**
+        * Get the number of rows affected by the last write query
+        * @see http://www.php.net/mysql_affected_rows
+        *
+        * @return int
+        */
+       abstract function affectedRows();
+
+       /**
+        * Wrapper for addslashes()
+        *
+        * @param string $s String to be slashed.
+        * @return string Slashed string.
+        */
+       abstract function strencode( $s );
+
+       /**
+        * Returns a wikitext link to the DB's website, e.g.,
+        *   return "[http://www.mysql.com/ MySQL]";
+        * Should at least contain plain text, if for some reason
+        * your database has no website.
+        *
+        * @return string Wikitext of a link to the server software's web site
+        */
+       abstract function getSoftwareLink();
+
+       /**
+        * A string describing the current software version, like from
+        * mysql_get_server_info().
+        *
+        * @return string Version information from the database server.
+        */
+       abstract function getServerVersion();
 
        /**
         * Constructor.
@@ -1049,7 +1198,13 @@ abstract class DatabaseBase implements IDatabase {
                        $this->reportQueryError( $this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore );
                }
 
-               return $this->resultObject( $ret );
+               $res = $this->resultObject( $ret );
+
+               // Destroy profile sections in the opposite order to their creation
+               $queryProfSection = false;
+               $totalProfSection = false;
+
+               return $res;
        }
 
        /**
index 7dfae63..430b20c 100644 (file)
@@ -1271,13 +1271,15 @@ class MySQLField implements Field {
 class MySQLMasterPos implements DBMasterPos {
        /** @var string */
        public $file;
-
-       /** @var int Timestamp */
+       /** @var int Position */
        public $pos;
+       /** @var float UNIX timestamp */
+       public $asOfTime = 0.0;
 
        function __construct( $file, $pos ) {
                $this->file = $file;
                $this->pos = $pos;
+               $this->asOfTime = microtime( true );
        }
 
        function __toString() {
@@ -1303,4 +1305,8 @@ class MySQLMasterPos implements DBMasterPos {
 
                return ( $thisPos && $thatPos && $thisPos >= $thatPos );
        }
+
+       function asOfTime() {
+               return $this->asOfTime;
+       }
 }
index f031f78..e150206 100644 (file)
@@ -229,7 +229,7 @@ class DatabaseOracle extends DatabaseBase {
                }
                $p['tablePrefix'] = strtoupper( $p['tablePrefix'] );
                parent::__construct( $p );
-               wfRunHooks( 'DatabaseOraclePostInit', array( $this ) );
+               Hooks::run( 'DatabaseOraclePostInit', array( $this ) );
        }
 
        function __destruct() {
index c1e80d3..4e5ed08 100644 (file)
@@ -339,4 +339,8 @@ class LikeMatch {
  * The implementation details of this opaque type are up to the database subclass.
  */
 interface DBMasterPos {
+       /**
+        * @return float UNIX timestamp
+        */
+       public function asOfTime();
 }
index 90e8867..f1b3238 100644 (file)
@@ -151,17 +151,23 @@ class LoadBalancer {
        /**
         * @param array $loads
         * @param bool|string $wiki Wiki to get non-lagged for
+        * @param float $maxLag Restrict the maximum allowed lag to this many seconds
         * @return bool|int|string
         */
-       private function getRandomNonLagged( array $loads, $wiki = false ) {
-               # Unset excessively lagged servers
+       private function getRandomNonLagged( array $loads, $wiki = false, $maxLag = INF ) {
                $lags = $this->getLagTimes( $wiki );
+
+               # Unset excessively lagged servers
                foreach ( $lags as $i => $lag ) {
                        if ( $i != 0 ) {
+                               $maxServerLag = $maxLag;
+                               if ( isset( $this->mServers[$i]['max lag'] ) ) {
+                                       $maxServerLag = min( $maxServerLag, $this->mServers[$i]['max lag'] );
+                               }
                                if ( $lag === false ) {
                                        wfDebugLog( 'replication', "Server #$i is not replicating" );
                                        unset( $loads[$i] );
-                               } elseif ( isset( $this->mServers[$i]['max lag'] ) && $lag > $this->mServers[$i]['max lag'] ) {
+                               } elseif ( $lag > $maxServerLag ) {
                                        wfDebugLog( 'replication', "Server #$i is excessively lagged ($lag seconds)" );
                                        unset( $loads[$i] );
                                }
@@ -252,7 +258,19 @@ class LoadBalancer {
                        if ( $wgReadOnly || $this->mAllowLagged || $laggedSlaveMode ) {
                                $i = ArrayUtils::pickRandom( $currentLoads );
                        } else {
-                               $i = $this->getRandomNonLagged( $currentLoads, $wiki );
+                               $i = false;
+                               if ( $this->mWaitForPos && $this->mWaitForPos->asOfTime() ) {
+                                       # ChronologyProtecter causes mWaitForPos to be set via sessions.
+                                       # This triggers doWait() after connect, so it's especially good to
+                                       # avoid lagged servers so as to avoid just blocking in that method.
+                                       $ago = microtime( true ) - $this->mWaitForPos->asOfTime();
+                                       # Aim for <= 1 second of waiting (being too picky can backfire)
+                                       $i = $this->getRandomNonLagged( $currentLoads, $wiki, $ago + 1 );
+                               }
+                               if ( $i === false ) {
+                                       # Any server with less lag than it's 'max lag' param is preferable
+                                       $i = $this->getRandomNonLagged( $currentLoads, $wiki );
+                               }
                                if ( $i === false && count( $currentLoads ) != 0 ) {
                                        # All slaves lagged. Switch to read-only mode
                                        wfDebugLog( 'replication', "All slaves lagged. Switch to read-only mode" );
index 45d2664..4e5af0b 100644 (file)
@@ -140,16 +140,16 @@ class LinksUpdate extends SqlDataUpdate {
 
                $this->mRecursive = $recursive;
 
-               wfRunHooks( 'LinksUpdateConstructed', array( &$this ) );
+               Hooks::run( 'LinksUpdateConstructed', array( &$this ) );
        }
 
        /**
         * Update link tables with outgoing links from an updated article
         */
        public function doUpdate() {
-               wfRunHooks( 'LinksUpdate', array( &$this ) );
+               Hooks::run( 'LinksUpdate', array( &$this ) );
                $this->doIncrementalUpdate();
-               wfRunHooks( 'LinksUpdateComplete', array( &$this ) );
+               Hooks::run( 'LinksUpdateComplete', array( &$this ) );
        }
 
        protected function doIncrementalUpdate() {
@@ -339,7 +339,7 @@ class LinksUpdate extends SqlDataUpdate {
                }
                if ( count( $insertions ) ) {
                        $this->mDb->insert( $table, $insertions, __METHOD__, 'IGNORE' );
-                       wfRunHooks( 'LinksUpdateAfterInsert', array( $this, $table, $insertions ) );
+                       Hooks::run( 'LinksUpdateAfterInsert', array( $this, $table, $insertions ) );
                }
        }
 
index 5d084af..8808c20 100644 (file)
@@ -80,7 +80,7 @@ class SearchUpdate implements DeferrableUpdate {
 
                wfProfileIn( __METHOD__ );
 
-               $page = WikiPage::newFromId( $this->id, WikiPage::READ_LATEST );
+               $page = WikiPage::newFromID( $this->id, WikiPage::READ_LATEST );
 
                foreach ( SearchEngine::getSearchTypes() as $type ) {
                        $search = SearchEngine::create( $type );
index dd5f3c7..c887193 100644 (file)
@@ -283,7 +283,7 @@ class DifferenceEngine extends ContextSource {
                        $samePage = true;
                        $oldHeader = '';
                } else {
-                       wfRunHooks( 'DiffViewHeader', array( $this, $this->mOldRev, $this->mNewRev ) );
+                       Hooks::run( 'DiffViewHeader', array( $this, $this->mOldRev, $this->mNewRev ) );
 
                        if ( $this->mNewPage->equals( $this->mOldPage ) ) {
                                $out->setPageTitle( $this->msg( 'difference-title', $this->mNewPage->getPrefixedText() ) );
@@ -387,7 +387,7 @@ class DifferenceEngine extends ContextSource {
                $rdel = $this->revisionDeleteLink( $this->mNewRev );
 
                # Allow extensions to define their own revision tools
-               wfRunHooks( 'DiffRevisionTools', array( $this->mNewRev, &$revisionTools, $this->mOldRev ) );
+               Hooks::run( 'DiffRevisionTools', array( $this->mNewRev, &$revisionTools, $this->mOldRev ) );
                $formattedRevisionTools = array();
                // Put each one in parentheses (poor man's button)
                foreach ( $revisionTools as $key => $tool ) {
@@ -555,7 +555,7 @@ class DifferenceEngine extends ContextSource {
                <h2 class='diff-currentversion-title'>{$revHeader}</h2>\n" );
                # Page content may be handled by a hooked call instead...
                # @codingStandardsIgnoreStart Ignoring long lines.
-               if ( wfRunHooks( 'ArticleContentOnDiff', array( $this, $out ) ) ) {
+               if ( Hooks::run( 'ArticleContentOnDiff', array( $this, $out ) ) ) {
                        $this->loadNewText();
                        $out->setRevisionId( $this->mNewid );
                        $out->setRevisionTimestamp( $this->mNewRev->getTimestamp() );
@@ -575,7 +575,7 @@ class DifferenceEngine extends ContextSource {
                                                $out->addParserOutputContent( $po );
                                        }
                                }
-                       } elseif ( !wfRunHooks( 'ArticleContentViewCustom', array( $this->mNewContent, $this->mNewPage, $out ) ) ) {
+                       } elseif ( !Hooks::run( 'ArticleContentViewCustom', array( $this->mNewContent, $this->mNewPage, $out ) ) ) {
                                // Handled by extension
                        } elseif ( !ContentHandler::runLegacyHooks( 'ArticleViewCustom', array( $this->mNewContent, $this->mNewPage, $out ) ) ) {
                                // NOTE: deprecated hook, B/C only
@@ -742,7 +742,7 @@ class DifferenceEngine extends ContextSource {
                $difftext = $this->generateContentDiffBody( $this->mOldContent, $this->mNewContent );
 
                // Save to cache for 7 days
-               if ( !wfRunHooks( 'AbortDiffCache', array( &$this ) ) ) {
+               if ( !Hooks::run( 'AbortDiffCache', array( &$this ) ) ) {
                        wfIncrStats( 'diff_uncacheable' );
                } elseif ( $key !== false && $difftext !== false ) {
                        wfIncrStats( 'diff_cache_miss' );
@@ -1224,7 +1224,7 @@ class DifferenceEngine extends ContextSource {
                        $this->mNewid = 0;
                }
 
-               wfRunHooks(
+               Hooks::run(
                        'NewDifferenceEngine',
                        array( $this->getTitle(), &$this->mOldid, &$this->mNewid, $old, $new )
                );
index 9db04cb..83801b6 100644 (file)
  */
 class MWExceptionHandler {
 
+       protected static $reservedMemory;
+       protected static $fatalErrorTypes = array(
+               E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR,
+               /* HHVM's FATAL_ERROR level */ 16777217,
+       );
+
        /**
         * Install handlers with PHP.
         */
        public static function installHandler() {
                set_exception_handler( array( 'MWExceptionHandler', 'handleException' ) );
                set_error_handler( array( 'MWExceptionHandler', 'handleError' ) );
+
+               // Reserve 16k of memory so we can report OOM fatals
+               self::$reservedMemory = str_repeat( ' ', 16384 );
+               register_shutdown_function(
+                       array( 'MWExceptionHandler', 'handleFatalError' )
+               );
        }
 
        /**
@@ -194,6 +206,9 @@ class MWExceptionHandler {
                        case E_USER_DEPRECATED:
                                $levelName = 'Deprecated';
                                break;
+                       case /* HHVM's FATAL_ERROR */ 16777217:
+                               $levelName = 'Fatal';
+                               break;
                        default:
                                $levelName = 'Unknown error';
                                break;
@@ -207,6 +222,44 @@ class MWExceptionHandler {
                return false;
        }
 
+
+       /**
+        * Look for a fatal error as the cause of the request termination and log
+        * as an exception.
+        *
+        * Special handling is included for missing class errors as they may
+        * indicate that the user needs to install 3rd-party libraries via
+        * Composer or other means.
+        *
+        * @since 1.25
+        */
+       public static function handleFatalError() {
+               self::$reservedMemory = null;
+               $lastError = error_get_last();
+
+               if ( $lastError &&
+                       isset( $lastError['type'] ) &&
+                       in_array( $lastError['type'], self::$fatalErrorTypes )
+               ) {
+                       $msg = "Fatal Error: {$lastError['message']}";
+                       // HHVM: Class undefined: foo
+                       // PHP5: Class 'foo' not found
+                       if ( preg_match( "/Class (undefined: \w+|'\w+' not found)/",
+                               $lastError['message']
+                       ) ) {
+                               $msg = <<<TXT
+{$msg}
+
+MediaWiki or an installed extension requires this class but it is not embedded directly in MediaWiki's git repository and must be installed separately by the end user.
+
+Please see <a href="https://www.mediawiki.org/wiki/Download_from_Git#Fetch_external_libraries">mediawiki.org</a> for help on installing the required components.
+TXT;
+                       }
+                       $e = new ErrorException( $msg, 0, $lastError['type'] );
+                       self::logError( $e );
+               }
+       }
+
        /**
         * Generate a string representation of an exception's stack trace
         *
index ae6b659..58311d3 100644 (file)
@@ -1125,7 +1125,7 @@ abstract class File {
                                $thumb = $this->transformErrorOutput( $thumbPath, $thumbUrl, $transformParams, $flags );
                        }
                        // Give extensions a chance to do something with this thumbnail...
-                       wfRunHooks( 'FileTransformed', array( $this, $thumb, $tmpThumbPath, $thumbPath ) );
+                       Hooks::run( 'FileTransformed', array( $this, $thumb, $tmpThumbPath, $thumbPath ) );
                }
 
                // Purge. Useful in the event of Core -> Squid connection failure or squid
index 9f14669..f1f8af4 100644 (file)
@@ -913,7 +913,7 @@ class LocalFile extends File {
                $files = $this->getThumbnails( $archiveName );
 
                // Purge any custom thumbnail caches
-               wfRunHooks( 'LocalFilePurgeThumbnails', array( $this, $archiveName ) );
+               Hooks::run( 'LocalFilePurgeThumbnails', array( $this, $archiveName ) );
 
                $dir = array_shift( $files );
                $this->purgeThumbList( $dir, $files );
@@ -958,7 +958,7 @@ class LocalFile extends File {
                }
 
                // Purge any custom thumbnail caches
-               wfRunHooks( 'LocalFilePurgeThumbnails', array( $this, false ) );
+               Hooks::run( 'LocalFilePurgeThumbnails', array( $this, false ) );
 
                $dir = array_shift( $files );
                $this->purgeThumbList( $dir, $files );
@@ -1035,7 +1035,7 @@ class LocalFile extends File {
                $opts['ORDER BY'] = "oi_timestamp $order";
                $opts['USE INDEX'] = array( 'oldimage' => 'oi_name_timestamp' );
 
-               wfRunHooks( 'LocalFile::getHistory', array( &$this, &$tables, &$fields,
+               Hooks::run( 'LocalFile::getHistory', array( &$this, &$tables, &$fields,
                        &$conds, &$opts, &$join_conds ) );
 
                $res = $dbr->select( $tables, $fields, $conds, __METHOD__, $opts, $join_conds );
@@ -1423,7 +1423,7 @@ class LocalFile extends File {
                        if ( !is_null( $nullRevision ) ) {
                                $nullRevision->insertOn( $dbw );
 
-                               wfRunHooks( 'NewRevisionFromEditComplete', array( $wikiPage, $nullRevision, $latest, $user ) );
+                               Hooks::run( 'NewRevisionFromEditComplete', array( $wikiPage, $nullRevision, $latest, $user ) );
                                $wikiPage->updateRevisionOn( $dbw, $nullRevision );
                        }
                }
@@ -1484,7 +1484,7 @@ class LocalFile extends File {
 
                # Hooks, hooks, the magic of hooks...
                wfProfileIn( __METHOD__ . '-hooks' );
-               wfRunHooks( 'FileUpload', array( $this, $reupload, $descTitle->exists() ) );
+               Hooks::run( 'FileUpload', array( $this, $reupload, $descTitle->exists() ) );
                wfProfileOut( __METHOD__ . '-hooks' );
 
                # Invalidate cache for all pages using this file
index b0a593d..bb9a903 100644 (file)
@@ -120,7 +120,7 @@ abstract class ImageGalleryBase extends ContextSource {
                                'packed-overlay' => 'PackedOverlayImageGallery',
                        );
                        // Allow extensions to make a new gallery format.
-                       wfRunHooks( 'GalleryGetModes', self::$modeMapping );
+                       Hooks::run( 'GalleryGetModes', self::$modeMapping );
                }
        }
 
index 37f2221..ac61067 100644 (file)
@@ -72,7 +72,7 @@ class TraditionalImageGallery extends ImageGalleryBase {
                                if ( $this->mParser instanceof Parser ) {
                                        # Give extensions a chance to select the file revision for us
                                        $options = array();
-                                       wfRunHooks( 'BeforeParserFetchFileAndTitle',
+                                       Hooks::run( 'BeforeParserFetchFileAndTitle',
                                                array( $this->mParser, $nt, &$options, &$descQuery ) );
                                        # Fetch and register the file (file title may be different via hooks)
                                        list( $img, $nt ) = $this->mParser->fetchFileAndTitle( $nt, $options );
index c34d09e..ea1213c 100644 (file)
@@ -115,7 +115,7 @@ abstract class DatabaseUpdater {
                $this->maintenance->setDB( $db );
                $this->initOldGlobals();
                $this->loadExtensions();
-               wfRunHooks( 'LoadExtensionSchemaUpdates', array( $this ) );
+               Hooks::run( 'LoadExtensionSchemaUpdates', array( $this ) );
        }
 
        /**
index 86b760c..ba84435 100644 (file)
@@ -48,7 +48,6 @@
        "config-env-good": "పర్యావరణాన్ని పరీక్షించాం.\nఇక మీరు MediaWiki ని స్థాపించుకోవచ్చు.",
        "config-env-bad": "పర్యావరణాన్ని పరీక్షించాం.\nమీరు MediaWiki ని స్థాపించలేరు.",
        "config-env-php": "PHP $1 స్థాపించబడింది.",
-       "config-env-php-toolow": "PHP $1 స్థాపించబడింది.\nఅయితే, MediaWiki కి PHP $2 గానీ ఆ పైది గానీ కావాలి.",
        "config-unicode-using-utf8": "యూనికోడు నార్మలైజేషన్ కోసం బ్రయాన్ విబర్ గారి utf8_normalize.so ను వాడుతున్నాం.",
        "config-unicode-using-intl": "యూనికోడు నార్మలైజేషన్ కోసం [http://pecl.php.net/intl intl PECL పొడిగింత] ను వాడుతున్నాం.",
        "config-outdated-sqlite": "<strong>హెచ్చరిక:</strong> మీ వద్ద SQLite $1 ఉంది. అదికావలసిన వెర్షను $2 కంటే దిగువది. SQLite అందుబాటులో ఉండదు.",
        "config-memcache-badport": "Memcached పోర్టు సఖ్యలు $1, $2 ల మధ్య ఉండాలి.",
        "config-extensions": "పొడిగింతలు",
        "config-extensions-help": "పైన చూపిన పొడిగింతలు మీ <code>./extensions</code> డైరెక్టరీలో ఉన్నాయి.\n\nవాటికి అదనంగా కాన్ఫిగరేషన్ అవసరం కావచ్చు. అయితే మీరు వాటిని చేతనం చెయ్యవచ్చు.",
+       "config-skins": "అలంకారాలు",
        "config-install-alreadydone": "<strong>హెచ్చరిక:</strong> మీరు ఈసరికే MediaWiki ని స్థాపించినట్లుగా అనిపిస్తోంది. మళ్ళీ స్థాపించే ప్రయత్నం చేస్తున్నట్లున్నారు.\nతరువాత పేజీకి వెళ్ళండి.",
        "config-install-begin": "\"{{int:config-continue}}\" నొక్కి, MediaWiki స్థాపనను మొదలుపెట్టవచ్చు.\nఇంకా మార్పులు చెయ్యదలిస్తే, \"{{int:config-back}}\" నొక్కండి.",
        "config-install-step-done": "పూర్తయింది",
index 4be4d98..923a80d 100644 (file)
@@ -3,14 +3,18 @@
                "authors": [
                        "පසිඳු කාවින්ද",
                        "Minh Nguyen",
-                       "Withoutaname"
+                       "Withoutaname",
+                       "Dinhxuanduyet"
                ]
        },
        "config-desc": "Trình cài đặt MediaWiki",
        "config-title": "Cài đặt MediaWiki $1",
        "config-information": "Thông tin",
+       "config-localsettings-upgrade": "Một file <code>LocalSettings.php</code> đã được phát hiện.\nĐể nâng cấp cài đặt này, xin nhập giá trị của  <code>$wgUpgradeKey</code> trong hộp thoại bên dưới đây.\nBạn sẽ tìm thấy nó trong<code>LocalSettings.php</code>.",
+       "config-localsettings-cli-upgrade": "Một file <code>LocalSettings.php</code> đã được phát hiện.\nĐể nâng cấp cài đặt này, hãy chạy <code>update.php</code>",
        "config-localsettings-key": "Chìa khóa nâng cấp:",
        "config-localsettings-badkey": "Bạn đã cung cấp một chìa khóa sai.",
+       "config-upgrade-key-missing": "Có một bản cài đặt của MediaWiki sẵn trước đó đã được phát hiện.\nĐể nâng cấp cài đặt này, hãy đặt dòng sau vào dưới của của <code>LocalSettings.php</code>:\n\n$1",
        "config-session-error": "Lỗi khi bắt đầu phiên làm việc: $1",
        "config-your-language": "Ngôn ngữ của bạn:",
        "config-your-language-help": "Chọn một ngôn ngữ để sử dụng trong quá trình cài đặt.",
index e12137e..0e03296 100644 (file)
        "config-license-gfdl": "GNU 自由文件授權條款 1.3 或更高版本",
        "config-license-pd": "公共領域",
        "config-license-cc-choose": "請選擇一個自訂的創作共用授權條款",
-       "config-license-help": "許多開放式 Wiki 會以 [http://freedomdefined.org/Definition 自由授權條款] 的方式釋放出編者的所有貢獻,這有助於構建社群的所有權,並且能鼓勵長期貢獻。對於封閉式的 Wiki 或公司 Wiki 則是非必要的。\n\n如果您希望使用來自維基百科(Wikipedia)的內容,並希望維基百科能接受您的 Wiki 內容,請應選擇 <strong>{{int:config-license-cc-by-sa}}</strong> 授權條款。\n\n維基百科̽(Wikipedia)先前是使用 GNU 自由文件授權條款,\n但該授權條款的內容較難理解,因此較難再利用在該條款底下的內容。",
+       "config-license-help": "許多開放式 Wiki 會以 [http://freedomdefined.org/Definition 自由授權條款] 的方式釋放出編者的所有貢獻,這有助於構建社群的所有權,並且能鼓勵長期貢獻。對於封閉式的 Wiki 或公司 Wiki 則是非必要的。\n\n如果您希望使用來自維基百科(Wikipedia)的內容,並希望維基百科能接受您的 Wiki 內容,請應選擇 <strong>{{int:config-license-cc-by-sa}}</strong> 授權條款。\n\n維基百科(Wikipedia)先前是使用 GNU 自由文件授權條款,\n但該授權條款的內容較難理解,因此較難再利用在該條款底下的內容。",
        "config-email-settings": "E-mail 設定",
        "config-enable-email": "開啟外寄電子郵件",
        "config-enable-email-help": "如果您要使用電子郵件功能,請正確設定 [http://www.php.net/manual/en/mail.configuration.php PHP 的郵件設定]。\n如果您不需要使用電子郵件功能,請在此處關閉。",
index 37a9fcf..02fbb08 100644 (file)
@@ -194,7 +194,7 @@ class Interwiki {
                global $wgMemc, $wgInterwikiExpiry;
 
                $iwData = array();
-               if ( !wfRunHooks( 'InterwikiLoadPrefix', array( $prefix, &$iwData ) ) ) {
+               if ( !Hooks::run( 'InterwikiLoadPrefix', array( $prefix, &$iwData ) ) ) {
                        return Interwiki::loadFromArray( $iwData );
                }
 
index db8a7ec..93ae83b 100644 (file)
@@ -117,7 +117,7 @@ abstract class GenericArrayObject extends ArrayObject {
         *
         * @param mixed $value
         *
-        * @return boolean
+        * @return bool
         */
        protected function hasValidType( $value ) {
                $class = $this->getObjectType();
@@ -171,7 +171,7 @@ abstract class GenericArrayObject extends ArrayObject {
         * @param integer|string $index
         * @param mixed $value
         *
-        * @return boolean
+        * @return bool
         */
        protected function preSetElement( $index, $value ) {
                return true;
@@ -232,7 +232,7 @@ abstract class GenericArrayObject extends ArrayObject {
         *
         * @since 1.20
         *
-        * @return boolean
+        * @return bool
         */
        public function isEmpty() {
                return $this->count() === 0;
index 3b9f1a8..c1c841e 100644 (file)
@@ -162,7 +162,7 @@ class IPSet {
         * Match an IP address against the set
         *
         * @param string $ip string IPv[46] address
-        * @return boolean true is match success, false is match failure
+        * @return bool true is match success, false is match failure
         *
         * If $ip is unparseable, inet_pton may issue an E_WARNING to that effect
         */
index 631b651..629c269 100644 (file)
 class ScopedCallback {
        /** @var callable */
        protected $callback;
+       /** @var array */
+       protected $params;
 
        /**
         * @param callable $callback
+        * @param array $params Callback arguments (since 1.25)
         * @throws Exception
         */
-       public function __construct( $callback ) {
+       public function __construct( $callback, array $params = array() ) {
                if ( !is_callable( $callback ) ) {
                        throw new InvalidArgumentException( "Provided callback is not valid." );
                }
                $this->callback = $callback;
+               $this->params = $params;
        }
 
        /**
@@ -67,7 +71,7 @@ class ScopedCallback {
         */
        function __destruct() {
                if ( $this->callback !== null ) {
-                       call_user_func( $this->callback );
+                       call_user_func_array( $this->callback, $this->params );
                }
        }
 }
index aca857e..0d6c3a6 100644 (file)
@@ -70,7 +70,7 @@ class XmlTypeCheck {
         *        SAX element handler event. This gives you access to the element
         *        namespace, name, attributes, and text contents.
         *        Filter should return 'true' to toggle on $this->filterMatch
-        * @param boolean $isFile (optional) indicates if the first parameter is a
+        * @param bool $isFile (optional) indicates if the first parameter is a
         *        filename (default, true) or if it is a string (false)
         * @param array $options list of additional parsing options:
         *        processing_instruction_handler: Callback for xml_set_processing_instruction_handler
index e03cf1c..f7eaec3 100644 (file)
@@ -273,7 +273,7 @@ class LogEventsList extends ContextSource {
                        } else {
                                // Allow extensions to add their own extra inputs
                                $input = '';
-                               wfRunHooks( 'LogEventsListGetExtraInputs', array( $types[0], $this, &$input ) );
+                               Hooks::run( 'LogEventsListGetExtraInputs', array( $types[0], $this, &$input ) );
                                return $input;
                        }
                }
@@ -632,7 +632,7 @@ class LogEventsList extends ContextSource {
                }
 
                /* hook can return false, if we don't want the message to be emitted (Wikia BugId:7093) */
-               if ( wfRunHooks( 'LogEventsListShowLogExtract', array( &$s, $types, $page, $user, $param ) ) ) {
+               if ( Hooks::run( 'LogEventsListShowLogExtract', array( &$s, $types, $page, $user, $param ) ) ) {
                        // $out can be either an OutputPage object or a String-by-reference
                        if ( $out instanceof OutputPage ) {
                                $out->addHTML( $s );
index bbe2f42..464b723 100644 (file)
@@ -812,7 +812,7 @@ class LegacyLogFormatter extends LogFormatter {
 
                $params = $this->entry->getParameters();
 
-               wfRunHooks( 'LogLine', array( $type, $subtype, $title, $params,
+               Hooks::run( 'LogLine', array( $type, $subtype, $title, $params,
                        &$this->comment, &$this->revert, $this->entry->getTimestamp() ) );
 
                return $this->revert;
index 8215403..220c6b1 100644 (file)
@@ -224,7 +224,7 @@ class EmailNotification {
 
                $formattedPageStatus = array( 'deleted', 'created', 'moved', 'restored', 'changed' );
 
-               wfRunHooks( 'UpdateUserMailerFormattedPageStatus', array( &$formattedPageStatus ) );
+               Hooks::run( 'UpdateUserMailerFormattedPageStatus', array( &$formattedPageStatus ) );
                if ( !in_array( $this->pageStatus, $formattedPageStatus ) ) {
                        wfProfileOut( __METHOD__ );
                        throw new MWException( 'Not a valid page status!' );
@@ -251,7 +251,7 @@ class EmailNotification {
                                                && $watchingUser->isEmailConfirmed()
                                                && $watchingUser->getID() != $userTalkId
                                        ) {
-                                               if ( wfRunHooks( 'SendWatchlistEmailNotification', array( $watchingUser, $title, $this ) ) ) {
+                                               if ( Hooks::run( 'SendWatchlistEmailNotification', array( $watchingUser, $title, $this ) ) ) {
                                                        $this->compose( $watchingUser );
                                                }
                                        }
@@ -295,7 +295,7 @@ class EmailNotification {
                        ) {
                                if ( !$targetUser->isEmailConfirmed() ) {
                                        wfDebug( __METHOD__ . ": talk page owner doesn't have validated email\n" );
-                               } elseif ( !wfRunHooks( 'AbortTalkPageEmailNotification', array( $targetUser, $title ) ) ) {
+                               } elseif ( !Hooks::run( 'AbortTalkPageEmailNotification', array( $targetUser, $title ) ) ) {
                                        wfDebug( __METHOD__ . ": talk page update notification is aborted for this user\n" );
                                } else {
                                        wfDebug( __METHOD__ . ": sending talk page update notification\n" );
index b5a57a8..3cabdae 100644 (file)
@@ -191,7 +191,7 @@ class UserMailer {
                $extraParams = $wgAdditionalMailParams;
 
                // Hook to generate custom VERP address for 'Return-Path'
-               wfRunHooks( 'UserMailerChangeReturnPath', array( $to, &$returnPath ) );
+               Hooks::run( 'UserMailerChangeReturnPath', array( $to, &$returnPath ) );
                # Add the envelope sender address using the -f command line option when PHP mail() is used.
                # Will default to the $from->address when the UserMailerChangeReturnPath hook fails and the
                # generated VERP address when the hook runs effectively.
@@ -250,7 +250,7 @@ class UserMailer {
                        $headers['Content-transfer-encoding'] = '8bit';
                }
 
-               $ret = wfRunHooks( 'AlternateUserMailer', array( $headers, $to, $from, $subject, $body ) );
+               $ret = Hooks::run( 'AlternateUserMailer', array( $headers, $to, $from, $subject, $body ) );
                if ( $ret === false ) {
                        // the hook implementation will return false to skip regular mail sending
                        return Status::newGood();
index 07d7618..8cf95dd 100644 (file)
@@ -1614,7 +1614,7 @@ class FormatMetadata extends ContextSource {
                $cachedValue = $wgMemc->get( $cacheKey );
                if (
                        $cachedValue
-                       && wfRunHooks( 'ValidateExtendedMetadataCache', array( $cachedValue['timestamp'], $file ) )
+                       && Hooks::run( 'ValidateExtendedMetadataCache', array( $cachedValue['timestamp'], $file ) )
                ) {
                        $extendedMetadata = $cachedValue['data'];
                } else {
@@ -1717,7 +1717,7 @@ class FormatMetadata extends ContextSource {
        ) {
                wfProfileIn( __METHOD__ );
 
-               wfRunHooks( 'GetExtendedMetadata', array(
+               Hooks::run( 'GetExtendedMetadata', array(
                        &$extendedMetadata,
                        $file,
                        $this->getContext(),
index 64ca011..b88a1b1 100644 (file)
@@ -162,7 +162,7 @@ abstract class MediaHandler {
         */
        static function getMetadataVersion() {
                $version = array( '2' ); // core metadata version
-               wfRunHooks( 'GetMetadataVersion', array( &$version ) );
+               Hooks::run( 'GetMetadataVersion', array( &$version ) );
 
                return implode( ';', $version );
        }
index d9327fb..a22cd1c 100644 (file)
@@ -410,7 +410,7 @@ class ThumbnailImage extends MediaTransformOutput {
                        $attribs['srcset'] = Html::srcSet( $this->responsiveUrls );
                }
 
-               wfRunHooks( 'ThumbnailBeforeProduceHTML', array( $this, &$attribs, &$linkAttribs ) );
+               Hooks::run( 'ThumbnailBeforeProduceHTML', array( $this, &$attribs, &$linkAttribs ) );
 
                return $this->linkWrap( $linkAttribs, Xml::element( 'img', $attribs ) );
        }
index b3ae296..5b9982d 100644 (file)
@@ -64,7 +64,7 @@ abstract class TransformationalImageHandler extends ImageHandler {
                # Check if the file is smaller than the maximum image area for thumbnailing
                # For historical reasons, hook starts with BitmapHandler
                $checkImageAreaHookResult = null;
-               wfRunHooks(
+               Hooks::run(
                        'BitmapHandlerCheckImageArea',
                        array( $image, &$params, &$checkImageAreaHookResult )
                );
@@ -240,7 +240,7 @@ abstract class TransformationalImageHandler extends ImageHandler {
                # Try a hook. Called "Bitmap" for historical reasons.
                /** @var $mto MediaTransformOutput */
                $mto = null;
-               wfRunHooks( 'BitmapHandlerTransform', array( $this, $image, &$scalerParams, &$mto ) );
+               Hooks::run( 'BitmapHandlerTransform', array( $this, $image, &$scalerParams, &$mto ) );
                if ( !is_null( $mto ) ) {
                        wfDebug( __METHOD__ . ": Hook to BitmapHandlerTransform created an mto\n" );
                        $scaler = 'hookaborted';
index cdbd5ab..5b46af1 100644 (file)
@@ -173,7 +173,7 @@ class XMPReader {
 
                $data = $this->results;
 
-               wfRunHooks( 'XMPGetResults', array( &$data ) );
+               Hooks::run( 'XMPGetResults', array( &$data ) );
 
                if ( isset( $data['xmp-special']['AuthorsPosition'] )
                        && is_string( $data['xmp-special']['AuthorsPosition'] )
index 7e47ec1..e0a491c 100644 (file)
@@ -34,7 +34,7 @@ class XMPInfo {
                if ( !self::$ranHooks ) {
                        // This is for if someone makes a custom metadata extension.
                        // For example, a medical wiki might want to decode DICOM xmp properties.
-                       wfRunHooks( 'XMPGetInfo', array( &self::$items ) );
+                       Hooks::run( 'XMPGetInfo', array( &self::$items ) );
                        self::$ranHooks = true; // Only want to do this once.
                }
 
index e3541bd..0318f65 100644 (file)
@@ -120,7 +120,7 @@ class Article implements Page {
                }
 
                $page = null;
-               wfRunHooks( 'ArticleFromTitle', array( &$title, &$page, $context ) );
+               Hooks::run( 'ArticleFromTitle', array( &$title, &$page, $context ) );
                if ( !$page ) {
                        switch ( $title->getNamespace() ) {
                                case NS_FILE:
@@ -428,7 +428,7 @@ class Article implements Page {
                );
                $this->mRevIdFetched = $this->mRevision->getId();
 
-               wfRunHooks( 'ArticleAfterFetchContentObject', array( &$this, &$this->mContentObject ) );
+               Hooks::run( 'ArticleAfterFetchContentObject', array( &$this, &$this->mContentObject ) );
 
                wfProfileOut( __METHOD__ );
 
@@ -602,7 +602,7 @@ class Article implements Page {
                while ( !$outputDone && ++$pass ) {
                        switch ( $pass ) {
                                case 1:
-                                       wfRunHooks( 'ArticleViewHeader', array( &$this, &$outputDone, &$useParserCache ) );
+                                       Hooks::run( 'ArticleViewHeader', array( &$this, &$outputDone, &$useParserCache ) );
                                        break;
                                case 2:
                                        # Early abort if the page doesn't exist
@@ -665,7 +665,7 @@ class Article implements Page {
                                                wfDebug( __METHOD__ . ": showing CSS/JS source\n" );
                                                $this->showCssOrJsPage();
                                                $outputDone = true;
-                                       } elseif ( !wfRunHooks( 'ArticleContentViewCustom',
+                                       } elseif ( !Hooks::run( 'ArticleContentViewCustom',
                                                        array( $this->fetchContentObject(), $this->getTitle(), $outputPage ) ) ) {
 
                                                # Allow extensions do their own custom view for certain pages
@@ -995,7 +995,7 @@ class Article implements Page {
                if ( isset( $this->mRedirectedFrom ) ) {
                        // This is an internally redirected page view.
                        // We'll need a backlink to the source page for navigation.
-                       if ( wfRunHooks( 'ArticleViewRedirect', array( &$this ) ) ) {
+                       if ( Hooks::run( 'ArticleViewRedirect', array( &$this ) ) ) {
                                $redir = Linker::linkKnown(
                                        $this->mRedirectedFrom,
                                        null,
@@ -1073,7 +1073,7 @@ class Article implements Page {
                // Show a footer allowing the user to patrol the shown revision or page if possible
                $patrolFooterShown = $this->showPatrolFooter();
 
-               wfRunHooks( 'ArticleViewFooter', array( $this, $patrolFooterShown ) );
+               Hooks::run( 'ArticleViewFooter', array( $this, $patrolFooterShown ) );
        }
 
        /**
@@ -1244,12 +1244,12 @@ class Article implements Page {
                        }
                }
 
-               wfRunHooks( 'ShowMissingArticle', array( $this ) );
+               Hooks::run( 'ShowMissingArticle', array( $this ) );
 
                // Give extensions a chance to hide their (unrelated) log entries
                $logTypes = array( 'delete', 'move' );
                $conds = array( "log_action != 'revision'" );
-               wfRunHooks( 'Article::MissingArticleConditions', array( &$conds, $logTypes ) );
+               Hooks::run( 'Article::MissingArticleConditions', array( &$conds, $logTypes ) );
 
                # Show delete and move logs
                LogEventsList::showLogExtract( $outputPage, $logTypes, $title, '',
@@ -1270,7 +1270,7 @@ class Article implements Page {
                $outputPage->setIndexPolicy( $policy['index'] );
                $outputPage->setFollowPolicy( $policy['follow'] );
 
-               $hookResult = wfRunHooks( 'BeforeDisplayNoArticleText', array( $this ) );
+               $hookResult = Hooks::run( 'BeforeDisplayNoArticleText', array( $this ) );
 
                if ( !$hookResult ) {
                        return;
@@ -1346,7 +1346,7 @@ class Article implements Page {
         * @param int $oldid Revision ID of this article revision
         */
        public function setOldSubtitle( $oldid = 0 ) {
-               if ( !wfRunHooks( 'DisplayOldSubtitle', array( &$this, &$oldid ) ) ) {
+               if ( !Hooks::run( 'DisplayOldSubtitle', array( &$this, &$oldid ) ) ) {
                        return;
                }
 
@@ -1697,7 +1697,7 @@ class Article implements Page {
                }
                $outputPage->addWikiMsg( 'confirmdeletetext' );
 
-               wfRunHooks( 'ArticleConfirmDelete', array( $this, $outputPage, &$reason ) );
+               Hooks::run( 'ArticleConfirmDelete', array( $this, $outputPage, &$reason ) );
 
                $user = $this->getContext()->getUser();
 
@@ -1808,7 +1808,7 @@ class Article implements Page {
 
                        $outputPage->addWikiMsg( 'deletedtext', wfEscapeWikiText( $deleted ), $loglink );
 
-                       wfRunHooks( 'ArticleDeleteAfterSuccess', array( $this->getTitle(), $outputPage ) );
+                       Hooks::run( 'ArticleDeleteAfterSuccess', array( $this->getTitle(), $outputPage ) );
 
                        $outputPage->returnToMain( false );
                } else {
@@ -1882,7 +1882,7 @@ class Article implements Page {
                                && !$this->mRedirectedFrom && !$this->getTitle()->isRedirect();
                        // Extension may have reason to disable file caching on some pages.
                        if ( $cacheable ) {
-                               $cacheable = wfRunHooks( 'IsFileCacheable', array( &$this ) );
+                               $cacheable = Hooks::run( 'IsFileCacheable', array( &$this ) );
                        }
                }
 
index 9abc6a8..03a5b89 100644 (file)
@@ -61,7 +61,7 @@ class CategoryPage extends Article {
                        return;
                }
 
-               if ( !wfRunHooks( 'CategoryPageView', array( &$this ) ) ) {
+               if ( !Hooks::run( 'CategoryPageView', array( &$this ) ) ) {
                        return;
                }
 
index 348eff1..b9f99c8 100644 (file)
@@ -76,7 +76,7 @@ class ImagePage extends Article {
                $this->fileLoaded = true;
 
                $this->displayImg = $img = false;
-               wfRunHooks( 'ImagePageFindFile', array( $this, &$img, &$this->displayImg ) );
+               Hooks::run( 'ImagePageFindFile', array( $this, &$img, &$this->displayImg ) );
                if ( !$img ) { // not set by hook?
                        $img = wfFindFile( $this->getTitle() );
                        if ( !$img ) {
@@ -196,7 +196,7 @@ class ImagePage extends Article {
 
                # Allow extensions to add something after the image links
                $html = '';
-               wfRunHooks( 'ImagePageAfterImageLinks', array( $this, &$html ) );
+               Hooks::run( 'ImagePageAfterImageLinks', array( $this, &$html ) );
                if ( $html ) {
                        $out->addHTML( $html );
                }
@@ -245,7 +245,7 @@ class ImagePage extends Article {
                        $r[] = '<li><a href="#metadata">' . wfMessage( 'metadata' )->escaped() . '</a></li>';
                }
 
-               wfRunHooks( 'ImagePageShowTOC', array( $this, &$r ) );
+               Hooks::run( 'ImagePageShowTOC', array( $this, &$r ) );
 
                return '<ul id="filetoc">' . implode( "\n", $r ) . '</ul>';
        }
@@ -336,7 +336,7 @@ class ImagePage extends Article {
                        $filename = wfEscapeWikiText( $this->displayImg->getName() );
                        $linktext = $filename;
 
-                       wfRunHooks( 'ImageOpenShowImageInlineBefore', array( &$this, &$out ) );
+                       Hooks::run( 'ImageOpenShowImageInlineBefore', array( &$this, &$out ) );
 
                        if ( $this->displayImg->allowInlineDisplay() ) {
                                # image
@@ -1384,7 +1384,7 @@ class ImageHistoryList extends ContextSource {
                }
 
                $rowClass = null;
-               wfRunHooks( 'ImagePageFileHistoryLine', array( $this, $file, &$row, &$rowClass ) );
+               Hooks::run( 'ImagePageFileHistoryLine', array( $this, $file, &$row, &$rowClass ) );
                $classAttr = $rowClass ? " class='$rowClass'" : '';
 
                return "<tr{$classAttr}>{$row}</tr>\n";
index 8b26c23..b9f7eda 100644 (file)
@@ -308,11 +308,11 @@ class WikiPage implements Page, IDBAccessObject {
        protected function pageData( $dbr, $conditions, $options = array() ) {
                $fields = self::selectFields();
 
-               wfRunHooks( 'ArticlePageDataBefore', array( &$this, &$fields ) );
+               Hooks::run( 'ArticlePageDataBefore', array( &$this, &$fields ) );
 
                $row = $dbr->selectRow( 'page', $fields, $conditions, __METHOD__, $options );
 
-               wfRunHooks( 'ArticlePageDataAfter', array( &$this, &$row ) );
+               Hooks::run( 'ArticlePageDataAfter', array( &$this, &$row ) );
 
                return $row;
        }
@@ -1178,7 +1178,7 @@ class WikiPage implements Page, IDBAccessObject {
        public function doPurge() {
                global $wgUseSquid;
 
-               if ( !wfRunHooks( 'ArticlePurge', array( &$this ) ) ) {
+               if ( !Hooks::run( 'ArticlePurge', array( &$this ) ) ) {
                        return false;
                }
 
@@ -1749,7 +1749,7 @@ class WikiPage implements Page, IDBAccessObject {
                $hook_args = array( &$this, &$user, &$content, &$summary,
                                                        $flags & EDIT_MINOR, null, null, &$flags, &$status );
 
-               if ( !wfRunHooks( 'PageContentSave', $hook_args )
+               if ( !Hooks::run( 'PageContentSave', $hook_args )
                        || !ContentHandler::runLegacyHooks( 'ArticleSave', $hook_args ) ) {
 
                        wfDebug( __METHOD__ . ": ArticleSave or ArticleSaveContent hook aborted save!\n" );
@@ -1783,7 +1783,7 @@ class WikiPage implements Page, IDBAccessObject {
                        $summary = $handler->getAutosummary( $old_content, $content, $flags );
                }
 
-               $editInfo = $this->prepareContentForEdit( $content, null, $user, $serialFormat, true );
+               $editInfo = $this->prepareContentForEdit( $content, null, $user, $serialFormat );
                $serialized = $editInfo->pst;
 
                /**
@@ -1860,7 +1860,7 @@ class WikiPage implements Page, IDBAccessObject {
                                                return $status;
                                        }
 
-                                       wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, $baseRevId, $user ) );
+                                       Hooks::run( 'NewRevisionFromEditComplete', array( $this, $revision, $baseRevId, $user ) );
                                        // Update recentchanges
                                        if ( !( $flags & EDIT_SUPPRESS_RC ) ) {
                                                // Mark as patrolled if the user can do so
@@ -1965,7 +1965,7 @@ class WikiPage implements Page, IDBAccessObject {
                                // Update the page record with revision data
                                $this->updateRevisionOn( $dbw, $revision, 0 );
 
-                               wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) );
+                               Hooks::run( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) );
 
                                // Update recentchanges
                                if ( !( $flags & EDIT_SUPPRESS_RC ) ) {
@@ -1996,7 +1996,7 @@ class WikiPage implements Page, IDBAccessObject {
                                                                $flags & EDIT_MINOR, null, null, &$flags, $revision );
 
                        ContentHandler::runLegacyHooks( 'ArticleInsertComplete', $hook_args );
-                       wfRunHooks( 'PageContentInsertComplete', $hook_args );
+                       Hooks::run( 'PageContentInsertComplete', $hook_args );
                }
 
                // Do updates right now unless deferral was requested
@@ -2011,7 +2011,7 @@ class WikiPage implements Page, IDBAccessObject {
                                                        $flags & EDIT_MINOR, null, null, &$flags, $revision, &$status, $baseRevId );
 
                ContentHandler::runLegacyHooks( 'ArticleSaveComplete', $hook_args );
-               wfRunHooks( 'PageContentSaveComplete', $hook_args );
+               Hooks::run( 'PageContentSaveComplete', $hook_args );
 
                // Promote user to any groups they meet the criteria for
                $dbw->onTransactionIdle( function () use ( $user ) {
@@ -2076,7 +2076,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @since 1.21
         */
        public function prepareContentForEdit(
-               Content $content, $revid = null, User $user = null, $serialFormat = null, $useCache = false
+               Content $content, $revid = null, User $user = null, $serialFormat = null, $useCache = true
        ) {
                global $wgContLang, $wgUser;
 
@@ -2105,7 +2105,7 @@ class WikiPage implements Page, IDBAccessObject {
                        : false;
 
                $popts = ParserOptions::newFromUserAndLang( $user, $wgContLang );
-               wfRunHooks( 'ArticlePrepareTextForEdit', array( $this, $popts ) );
+               Hooks::run( 'ArticlePrepareTextForEdit', array( $this, $popts ) );
 
                $edit = (object)array();
                if ( $cachedEdit ) {
@@ -2203,9 +2203,9 @@ class WikiPage implements Page, IDBAccessObject {
                        DataUpdate::runUpdates( $updates );
                }
 
-               wfRunHooks( 'ArticleEditUpdates', array( &$this, &$editInfo, $options['changed'] ) );
+               Hooks::run( 'ArticleEditUpdates', array( &$this, &$editInfo, $options['changed'] ) );
 
-               if ( wfRunHooks( 'ArticleEditUpdatesDeleteFromRecentchanges', array( &$this ) ) ) {
+               if ( Hooks::run( 'ArticleEditUpdatesDeleteFromRecentchanges', array( &$this ) ) ) {
                        if ( 0 == mt_rand( 0, 99 ) ) {
                                // Flush old entries from the `recentchanges` table; we do this on
                                // random requests so as to avoid an increase in writes for no good reason
@@ -2250,7 +2250,7 @@ class WikiPage implements Page, IDBAccessObject {
                                wfDebug( __METHOD__ . ": invalid username\n" );
                        } else {
                                // Allow extensions to prevent user notification when a new message is added to their talk page
-                               if ( wfRunHooks( 'ArticleEditUpdateNewTalk', array( &$this, $recipient ) ) ) {
+                               if ( Hooks::run( 'ArticleEditUpdateNewTalk', array( &$this, $recipient ) ) ) {
                                        if ( User::isIP( $shortTitle ) ) {
                                                // An anonymous user
                                                $recipient->setNewtalk( true, $revision );
@@ -2333,7 +2333,7 @@ class WikiPage implements Page, IDBAccessObject {
                $revision->insertOn( $dbw );
                $this->updateRevisionOn( $dbw, $revision );
 
-               wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) );
+               Hooks::run( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) );
 
                wfProfileOut( __METHOD__ );
        }
@@ -2432,7 +2432,7 @@ class WikiPage implements Page, IDBAccessObject {
                $logRelationsField = null;
 
                if ( $id ) { // Protection of existing page
-                       if ( !wfRunHooks( 'ArticleProtect', array( &$this, &$user, $limit, $reason ) ) ) {
+                       if ( !Hooks::run( 'ArticleProtect', array( &$this, &$user, $limit, $reason ) ) ) {
                                return Status::newGood();
                        }
 
@@ -2512,8 +2512,8 @@ class WikiPage implements Page, IDBAccessObject {
                                __METHOD__
                        );
 
-                       wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $nullRevision, $latest, $user ) );
-                       wfRunHooks( 'ArticleProtectComplete', array( &$this, &$user, $limit, $reason ) );
+                       Hooks::run( 'NewRevisionFromEditComplete', array( $this, $nullRevision, $latest, $user ) );
+                       Hooks::run( 'ArticleProtectComplete', array( &$this, &$user, $limit, $reason ) );
                } else { // Protection of non-existing page (also known as "title protection")
                        // Cascade protection is meaningless in this case
                        $cascade = false;
@@ -2775,7 +2775,7 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                $user = is_null( $user ) ? $wgUser : $user;
-               if ( !wfRunHooks( 'ArticleDelete', array( &$this, &$user, &$reason, &$error, &$status ) ) ) {
+               if ( !Hooks::run( 'ArticleDelete', array( &$this, &$user, &$reason, &$error, &$status ) ) ) {
                        if ( $status->isOK() ) {
                                // Hook aborted but didn't set a fatal status
                                $status->fatal( 'delete-hook-aborted' );
@@ -2891,7 +2891,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                $this->doDeleteUpdates( $id, $content );
 
-               wfRunHooks( 'ArticleDeleteComplete', array( &$this, &$user, $reason, $id, $content, $logEntry ) );
+               Hooks::run( 'ArticleDeleteComplete', array( &$this, &$user, $reason, $id, $content, $logEntry ) );
                $status->value = $logid;
                return $status;
        }
@@ -3133,7 +3133,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                $revId = $status->value['revision']->getId();
 
-               wfRunHooks( 'ArticleRollbackComplete', array( $this, $guser, $target, $current ) );
+               Hooks::run( 'ArticleRollbackComplete', array( $this, $guser, $target, $current ) );
 
                $resultDetails = array(
                        'summary' => $summary,
@@ -3385,12 +3385,12 @@ class WikiPage implements Page, IDBAccessObject {
 
                                foreach ( $added as $catName ) {
                                        $cat = Category::newFromName( $catName );
-                                       wfRunHooks( 'CategoryAfterPageAdded', array( $cat, $that ) );
+                                       Hooks::run( 'CategoryAfterPageAdded', array( $cat, $that ) );
                                }
 
                                foreach ( $deleted as $catName ) {
                                        $cat = Category::newFromName( $catName );
-                                       wfRunHooks( 'CategoryAfterPageRemoved', array( $cat, $that ) );
+                                       Hooks::run( 'CategoryAfterPageRemoved', array( $cat, $that ) );
                                }
                        }
                );
@@ -3543,7 +3543,7 @@ class WikiPage implements Page, IDBAccessObject {
                        $updates = $content->getDeletionUpdates( $this );
                }
 
-               wfRunHooks( 'WikiPageDeletionUpdates', array( $this, $content, &$updates ) );
+               Hooks::run( 'WikiPageDeletionUpdates', array( $this, $content, &$updates ) );
                return $updates;
        }
 }
index 6c15993..0121072 100644 (file)
@@ -378,7 +378,7 @@ class LinkHolderArray {
                }
                if ( count( $linkcolour_ids ) ) {
                        //pass an array of page_ids to an extension
-                       wfRunHooks( 'GetLinkColours', array( $linkcolour_ids, &$colours ) );
+                       Hooks::run( 'GetLinkColours', array( $linkcolour_ids, &$colours ) );
                }
                wfProfileOut( __METHOD__ . '-check' );
 
@@ -615,7 +615,7 @@ class LinkHolderArray {
                                        }
                                }
                        }
-                       wfRunHooks( 'GetLinkColours', array( $linkcolour_ids, &$colours ) );
+                       Hooks::run( 'GetLinkColours', array( $linkcolour_ids, &$colours ) );
 
                        // rebuild the categories in original order (if there are replacements)
                        if ( count( $varCategories ) > 0 ) {
index 3cb35f7..7b53776 100644 (file)
@@ -131,12 +131,12 @@ class MWTidy {
                $wrappedtext = $wrapper->getWrapped( $text );
 
                $retVal = null;
-               $correctedtext = self::clean( $wrappedtext, false, $retVal );
+               list( $correctedtext, $errors ) = self::clean( $wrappedtext, $retVal );
 
                if ( $retVal < 0 ) {
                        wfDebug( "Possible tidy configuration error!\n" );
                        return $text . "\n<!-- Tidy was unable to run -->\n";
-               } elseif ( is_null( $correctedtext ) ) {
+               } elseif ( $correctedtext === '' && $text !== '' ) {
                        wfDebug( "Tidy error detected!\n" );
                        return $text . "\n<!-- Tidy found serious XHTML errors -->\n";
                }
@@ -155,31 +155,23 @@ class MWTidy {
         */
        public static function checkErrors( $text, &$errorStr = null ) {
                $retval = 0;
-               $errorStr = self::clean( $text, true, $retval );
+               list( $outputStr, $errorStr ) = self::clean( $text, $retval );
                return ( $retval < 0 && $errorStr == '' ) || $retval == 0;
        }
 
        /**
         * Perform a clean/repair operation
         * @param string $text HTML to check
-        * @param bool $stderr Whether to read result from STDERR rather than STDOUT
         * @param int &$retval Exit code (-1 on internal error)
         * @return string|null
         */
-       private static function clean( $text, $stderr = false, &$retval = null ) {
+       private static function clean( $text, &$retval = null ) {
                global $wgTidyInternal;
 
                if ( $wgTidyInternal ) {
-                       if ( wfIsHHVM() ) {
-                               if ( $stderr ) {
-                                       throw new MWException( __METHOD__ . ": error text return from HHVM tidy is not supported" );
-                               }
-                               return self::hhvmClean( $text, $retval );
-                       } else {
-                               return self::phpClean( $text, $stderr, $retval );
-                       }
+                       return self::internalClean( $text, $retval );
                } else {
-                       return self::externalClean( $text, $stderr, $retval );
+                       return self::externalClean( $text, $retval );
                }
        }
 
@@ -188,32 +180,23 @@ class MWTidy {
         * Also called in OutputHandler.php for full page validation
         *
         * @param string $text HTML to check
-        * @param bool $stderr Whether to read result from STDERR rather than STDOUT
         * @param int &$retval Exit code (-1 on internal error)
         * @return string|null
         */
-       private static function externalClean( $text, $stderr = false, &$retval = null ) {
+       private static function externalClean( $text, &$retval = null ) {
                global $wgTidyConf, $wgTidyBin, $wgTidyOpts;
                wfProfileIn( __METHOD__ );
 
-               $cleansource = '';
                $opts = ' -utf8';
 
-               if ( $stderr ) {
-                       $descriptorspec = array(
-                               0 => array( 'pipe', 'r' ),
-                               1 => array( 'file', wfGetNull(), 'a' ),
-                               2 => array( 'pipe', 'w' )
-                       );
-               } else {
-                       $descriptorspec = array(
-                               0 => array( 'pipe', 'r' ),
-                               1 => array( 'pipe', 'w' ),
-                               2 => array( 'file', wfGetNull(), 'a' )
-                       );
-               }
+               $descriptorspec = array(
+                       0 => array( 'pipe', 'r' ),
+                       1 => array( 'pipe', 'w' ),
+                       2 => array( 'pipe', 'w' ),
+               );
 
-               $readpipe = $stderr ? 2 : 1;
+               $outputBuffer = '';
+               $errorBuffer = '';
                $pipes = array();
 
                $process = proc_open(
@@ -230,24 +213,25 @@ class MWTidy {
                        // for tidyParseStdin and tidySaveStdout in console/tidy.c
                        fwrite( $pipes[0], $text );
                        fclose( $pipes[0] );
-                       while ( !feof( $pipes[$readpipe] ) ) {
-                               $cleansource .= fgets( $pipes[$readpipe], 1024 );
+
+                       while ( !feof( $pipes[1] ) ) {
+                               $outputBuffer .= fgets( $pipes[1], 1024 );
                        }
-                       fclose( $pipes[$readpipe] );
+                       fclose( $pipes[1] );
+
+                       while ( !feof( $pipes[2] ) ) {
+                               $errorBuffer .= fgets( $pipes[2], 1024 );
+                       }
+                       fclose( $pipes[2] );
+
                        $retval = proc_close( $process );
                } else {
                        wfWarn( "Unable to start external tidy process" );
                        $retval = -1;
                }
 
-               if ( !$stderr && $cleansource == '' && $text != '' ) {
-                       // Some kind of error happened, so we couldn't get the corrected text.
-                       // Just give up; we'll use the source text and append a warning.
-                       $cleansource = null;
-               }
-
                wfProfileOut( __METHOD__ );
-               return $cleansource;
+               return array( $outputBuffer, $errorBuffer );
        }
 
        /**
@@ -255,15 +239,16 @@ class MWTidy {
         * saving the overhead of spawning a new process.
         *
         * @param string $text HTML to check
-        * @param bool $stderr Whether to read result from error status instead of output
         * @param int &$retval Exit code (-1 on internal error)
         * @return string|null
         */
-       private static function phpClean( $text, $stderr = false, &$retval = null ) {
+       private static function internalClean( $text, &$retval = null ) {
                global $wgTidyConf, $wgDebugTidy;
                wfProfileIn( __METHOD__ );
 
-               if ( !class_exists( 'tidy' ) ) {
+               if ( ( !wfIsHHVM() && !class_exists( 'tidy' ) ) ||
+                       ( wfIsHHVM() && !function_exists( 'tidy_repair_string' ) )
+               ) {
                        wfWarn( "Unable to load internal tidy class." );
                        $retval = -1;
 
@@ -271,57 +256,36 @@ class MWTidy {
                        return null;
                }
 
-               $tidy = new tidy;
-               $tidy->parseString( $text, $wgTidyConf, 'utf8' );
-
-               if ( $stderr ) {
-                       $retval = $tidy->getStatus();
-
-                       wfProfileOut( __METHOD__ );
-                       return $tidy->errorBuffer;
-               }
-
-               $tidy->cleanRepair();
-               $retval = $tidy->getStatus();
-               if ( $retval == 2 ) {
-                       // 2 is magic number for fatal error
-                       // http://www.php.net/manual/en/function.tidy-get-status.php
-                       $cleansource = null;
+               $outputBuffer = '';
+               $errorBuffer = '';
+
+               if ( wfIsHHVM() ) {
+                       // Use the tidy extension for HHVM from
+                       // https://github.com/wikimedia/mediawiki-php-tidy
+                       //
+                       // This currently does not support the object-oriented interface, but
+                       // tidy_repair_string() can be used for the most common tasks.
+                       $result = tidy_repair_string( $text, $wgTidyConf, 'utf8' );
+                       $outputBuffer .= $result;
+                       $retval = $result === false ? -1 : 0;
                } else {
-                       $cleansource = tidy_get_output( $tidy );
-                       if ( $wgDebugTidy && $retval > 0 ) {
-                               $cleansource .= "<!--\nTidy reports:\n" .
-                                       str_replace( '-->', '--&gt;', $tidy->errorBuffer ) .
-                                       "\n-->";
+                       $tidy = new tidy;
+                       $tidy->parseString( $text, $wgTidyConf, 'utf8' );
+                       $tidy->cleanRepair();
+                       $retval = $tidy->getStatus();
+                       $outputBuffer .= tidy_get_output( $tidy );
+                       if ( $retval > 0 ) {
+                               $errorBuffer .= $tidy->errorBuffer;
                        }
                }
 
-               wfProfileOut( __METHOD__ );
-               return $cleansource;
-       }
-
-       /**
-        * Use the tidy extension for HHVM from
-        * https://github.com/wikimedia/mediawiki-php-tidy
-        *
-        * This currently does not support the object-oriented interface, but
-        * tidy_repair_string() can be used for the most common tasks.
-        *
-        * @param string $text HTML to check
-        * @param int &$retval Exit code (-1 on internal error)
-        * @return string|null
-        */
-       private static function hhvmClean( $text, &$retval ) {
-               global $wgTidyConf;
-               wfProfileIn( __METHOD__ );
-               $cleansource = tidy_repair_string( $text, $wgTidyConf, 'utf8' );
-               if ( $cleansource === false ) {
-                       $cleansource = null;
-                       $retval = -1;
-               } else {
-                       $retval = 0;
+               if ( $wgDebugTidy && $errorBuffer && $retval > 0 ) {
+                       $outputBuffer .= "<!--\nTidy reports:\n" .
+                               str_replace( '-->', '--&gt;', $tidy->errorBuffer ) .
+                               "\n-->";
                }
+
                wfProfileOut( __METHOD__ );
-               return $cleansource;
+               return array( $outputBuffer, $errorBuffer );
        }
 }
index 7ea57be..5c8253a 100644 (file)
@@ -283,7 +283,7 @@ class Parser {
                        unset( $tmp );
                }
 
-               wfRunHooks( 'ParserCloned', array( $this ) );
+               Hooks::run( 'ParserCloned', array( $this ) );
        }
 
        /**
@@ -301,7 +301,7 @@ class Parser {
                CoreTagHooks::register( $this );
                $this->initialiseVariables();
 
-               wfRunHooks( 'ParserFirstCallInit', array( &$this ) );
+               Hooks::run( 'ParserFirstCallInit', array( &$this ) );
                wfProfileOut( __METHOD__ );
        }
 
@@ -369,7 +369,7 @@ class Parser {
 
                $this->mProfiler = new SectionProfiler();
 
-               wfRunHooks( 'ParserClearState', array( &$this ) );
+               Hooks::run( 'ParserClearState', array( &$this ) );
                wfProfileOut( __METHOD__ );
        }
 
@@ -428,11 +428,11 @@ class Parser {
                        $this->mRevisionSize = null;
                }
 
-               wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
                # No more strip!
-               wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
                $text = $this->internalParse( $text );
-               wfRunHooks( 'ParserAfterParse', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'ParserAfterParse', array( &$this, &$text, &$this->mStripState ) );
 
                $text = $this->internalParseHalfParsed( $text, true, $linestart );
 
@@ -498,14 +498,14 @@ class Parser {
                        $this->mOutput->setLimitReportData( 'limitreport-expensivefunctioncount',
                                array( $this->mExpensiveFunctionCount, $this->mOptions->getExpensiveParserFunctionLimit() )
                        );
-                       wfRunHooks( 'ParserLimitReportPrepare', array( $this, $this->mOutput ) );
+                       Hooks::run( 'ParserLimitReportPrepare', array( $this, $this->mOutput ) );
 
                        $limitReport = "NewPP limit report\n";
                        if ( $wgShowHostnames ) {
                                $limitReport .= 'Parsed by ' . wfHostname() . "\n";
                        }
                        foreach ( $this->mOutput->getLimitReportData() as $key => $value ) {
-                               if ( wfRunHooks( 'ParserLimitReportFormat',
+                               if ( Hooks::run( 'ParserLimitReportFormat',
                                        array( $key, &$value, &$limitReport, false, false )
                                ) ) {
                                        $keyMsg = wfMessage( $key )->inLanguage( 'en' )->useDatabase( false );
@@ -523,7 +523,7 @@ class Parser {
                        // Since we're not really outputting HTML, decode the entities and
                        // then re-encode the things that need hiding inside HTML comments.
                        $limitReport = htmlspecialchars_decode( $limitReport );
-                       wfRunHooks( 'ParserLimitReport', array( $this, &$limitReport ) );
+                       Hooks::run( 'ParserLimitReport', array( $this, &$limitReport ) );
 
                        // Sanitize for comment. Note '‐' in the replacement is U+2010,
                        // which looks much like the problematic '-'.
@@ -587,8 +587,8 @@ class Parser {
         */
        public function recursiveTagParse( $text, $frame = false ) {
                wfProfileIn( __METHOD__ );
-               wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
-               wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
                $text = $this->internalParse( $text, false, $frame );
                wfProfileOut( __METHOD__ );
                return $text;
@@ -637,8 +637,8 @@ class Parser {
                if ( $revid !== null ) {
                        $this->mRevisionId = $revid;
                }
-               wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
-               wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
                $text = $this->replaceVariables( $text, $frame );
                $text = $this->mStripState->unstripBoth( $text );
                wfProfileOut( __METHOD__ );
@@ -1223,7 +1223,7 @@ class Parser {
                $origText = $text;
 
                # Hook to suspend the parser in this state
-               if ( !wfRunHooks( 'ParserBeforeInternalParse', array( &$this, &$text, &$this->mStripState ) ) ) {
+               if ( !Hooks::run( 'ParserBeforeInternalParse', array( &$this, &$text, &$this->mStripState ) ) ) {
                        wfProfileOut( __METHOD__ );
                        return $text;
                }
@@ -1244,14 +1244,14 @@ class Parser {
                        $text = $this->replaceVariables( $text );
                }
 
-               wfRunHooks( 'InternalParseBeforeSanitize', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'InternalParseBeforeSanitize', array( &$this, &$text, &$this->mStripState ) );
                $text = Sanitizer::removeHTMLtags(
                        $text,
                        array( &$this, 'attributeStripCallback' ),
                        false,
                        array_keys( $this->mTransparentTagHooks )
                );
-               wfRunHooks( 'InternalParseBeforeLinks', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'InternalParseBeforeLinks', array( &$this, &$text, &$this->mStripState ) );
 
                # Tables need to come after variable replacement for things to work
                # properly; putting them before other transformations should keep
@@ -1329,7 +1329,7 @@ class Parser {
                $text = $this->mStripState->unstripNoWiki( $text );
 
                if ( $isMain ) {
-                       wfRunHooks( 'ParserBeforeTidy', array( &$this, &$text ) );
+                       Hooks::run( 'ParserBeforeTidy', array( &$this, &$text ) );
                }
 
                $text = $this->replaceTransparentTags( $text );
@@ -1368,7 +1368,7 @@ class Parser {
                }
 
                if ( $isMain ) {
-                       wfRunHooks( 'ParserAfterTidy', array( &$this, &$text ) );
+                       Hooks::run( 'ParserAfterTidy', array( &$this, &$text ) );
                }
 
                return $text;
@@ -1393,13 +1393,13 @@ class Parser {
                        '!(?:                           # Start cases
                                (<a[ \t\r\n>].*?</a>) |     # m[1]: Skip link text
                                (<.*?>) |                   # m[2]: Skip stuff inside HTML elements' . "
-                               (\\b(?i:$prots)$urlChar+) |  # m[3]: Free external links" . '
-                               (?:RFC|PMID)\s+([0-9]+) |   # m[4]: RFC or PMID, capture number
-                               ISBN\s+(\b                  # m[5]: ISBN, capture number
+                               (\b(?i:$prots)$urlChar+) |  # m[3]: Free external links" . '
+                               \b(?:RFC|PMID)\s+([0-9]+)\b |# m[4]: RFC or PMID, capture number
+                               \bISBN\s+(                  # m[5]: ISBN, capture number
                                        (?: 97[89] [\ \-]? )?   # optional 13-digit ISBN prefix
                                        (?: [0-9]  [\ \-]? ){9} # 9 digits with opt. delimiters
                                        [0-9Xx]                 # check digit
-                                       \b)
+                                       )\b
                        )!xu', array( &$this, 'magicLinkCallback' ), $text );
                wfProfileOut( __METHOD__ );
                return $text;
@@ -2318,7 +2318,7 @@ class Parser {
                                # Give extensions a chance to select the file revision for us
                                $options = array();
                                $descQuery = false;
-                               wfRunHooks( 'BeforeParserFetchFileAndTitle',
+                               Hooks::run( 'BeforeParserFetchFileAndTitle',
                                        array( $this, $nt, &$options, &$descQuery ) );
                                # Fetch and register the file (file title may be different via hooks)
                                list( $file, $nt ) = $this->fetchFileAndTitle( $nt, $options );
@@ -2945,14 +2945,14 @@ class Parser {
                 * Some of these require message or data lookups and can be
                 * expensive to check many times.
                 */
-               if ( wfRunHooks( 'ParserGetVariableValueVarCache', array( &$this, &$this->mVarCache ) ) ) {
+               if ( Hooks::run( 'ParserGetVariableValueVarCache', array( &$this, &$this->mVarCache ) ) ) {
                        if ( isset( $this->mVarCache[$index] ) ) {
                                return $this->mVarCache[$index];
                        }
                }
 
                $ts = wfTimestamp( TS_UNIX, $this->mOptions->getTimestamp() );
-               wfRunHooks( 'ParserGetVariableValueTs', array( &$this, &$ts ) );
+               Hooks::run( 'ParserGetVariableValueTs', array( &$this, &$ts ) );
 
                $pageLang = $this->getFunctionLang();
 
@@ -3260,7 +3260,7 @@ class Parser {
                                break;
                        default:
                                $ret = null;
-                               wfRunHooks(
+                               Hooks::run(
                                        'ParserGetVariableValueSwitch',
                                        array( &$this, &$this->mVarCache, &$index, &$ret, &$frame )
                                );
@@ -4011,7 +4011,7 @@ class Parser {
                for ( $i = 0; $i < 2 && is_object( $title ); $i++ ) {
                        # Give extensions a chance to select the revision instead
                        $id = false; # Assume current
-                       wfRunHooks( 'BeforeParserFetchTemplateAndtitle',
+                       Hooks::run( 'BeforeParserFetchTemplateAndtitle',
                                array( $parser, $title, &$skip, &$id ) );
 
                        if ( $skip ) {
@@ -4820,7 +4820,7 @@ class Parser {
                         * &$sectionContent : ref to the content of the section
                         * $showEditLinks : boolean describing whether this section has an edit link
                         */
-                       wfRunHooks( 'ParserSectionCreate', array( $this, $i, &$sections[$i], $showEditLink ) );
+                       Hooks::run( 'ParserSectionCreate', array( $this, $i, &$sections[$i], $showEditLink ) );
 
                        $i++;
                }
@@ -5403,7 +5403,7 @@ class Parser {
                }
                $ig->setAdditionalOptions( $params );
 
-               wfRunHooks( 'BeforeParserrenderImageGallery', array( &$this, &$ig ) );
+               Hooks::run( 'BeforeParserrenderImageGallery', array( &$this, &$ig ) );
 
                $lines = StringUtils::explode( "\n", $text );
                foreach ( $lines as $line ) {
@@ -5430,7 +5430,7 @@ class Parser {
                        # file (which potentially could be of a different type and have different handler).
                        $options = array();
                        $descQuery = false;
-                       wfRunHooks( 'BeforeParserFetchFileAndTitle',
+                       Hooks::run( 'BeforeParserFetchFileAndTitle',
                                array( $this, $title, &$options, &$descQuery ) );
                        # Don't register it now, as ImageGallery does that later.
                        $file = $this->fetchFileNoRegister( $title, $options );
@@ -5511,7 +5511,7 @@ class Parser {
                        $ig->add( $title, $label, $alt, $link, $handlerOptions );
                }
                $html = $ig->toHTML();
-               wfRunHooks( 'AfterParserFetchFileAndTitle', array( $this, $ig, &$html ) );
+               Hooks::run( 'AfterParserFetchFileAndTitle', array( $this, $ig, &$html ) );
                wfProfileOut( __METHOD__ );
                return $html;
        }
@@ -5600,7 +5600,7 @@ class Parser {
                # Give extensions a chance to select the file revision for us
                $options = array();
                $descQuery = false;
-               wfRunHooks( 'BeforeParserFetchFileAndTitle',
+               Hooks::run( 'BeforeParserFetchFileAndTitle',
                        array( $this, $title, &$options, &$descQuery ) );
                # Fetch and register the file (file title may be different via hooks)
                list( $file, $title ) = $this->fetchFileAndTitle( $title, $options );
@@ -5764,7 +5764,7 @@ class Parser {
                        $params['frame']['title'] = $this->stripAltText( $caption, $holders );
                }
 
-               wfRunHooks( 'ParserMakeImageParams', array( $title, $file, &$params, $this ) );
+               Hooks::run( 'ParserMakeImageParams', array( $title, $file, &$params, $this ) );
 
                # Linker does the rest
                $time = isset( $options['time'] ) ? $options['time'] : false;
index b570fa5..7ad85a9 100644 (file)
@@ -641,6 +641,7 @@ class ParserOptions {
 
                wfProfileIn( __METHOD__ );
 
+               // *UPDATE* ParserOptions::matches() if any of this changes as needed
                $this->mInterwikiMagic = $wgInterwikiMagic;
                $this->mAllowExternalImages = $wgAllowExternalImages;
                $this->mAllowExternalImagesFrom = $wgAllowExternalImagesFrom;
@@ -666,6 +667,32 @@ class ParserOptions {
                wfProfileOut( __METHOD__ );
        }
 
+       /**
+        * Check if these options match that of another options set
+        *
+        * This ignores report limit settings that only affect HTML comments
+        *
+        * @return bool
+        * @since 1.25
+        */
+       public function matches( ParserOptions $other ) {
+               $fields = array_keys( get_class_vars( __CLASS__ ) );
+               $fields = array_diff( $fields, array(
+                       'mEnableLimitReport', // only effects HTML comments
+                       'onAccessCallback', // only used for ParserOutput option tracking
+               ) );
+               foreach ( $fields as $field ) {
+                       if ( !is_object( $this->$field ) && $this->$field !== $other->$field ) {
+                               return false;
+                       }
+               }
+               // Check the object and lazy-loaded options
+               return (
+                       $this->mUserLang->getCode() === $other->mUserLang->getCode() &&
+                       $this->getDateFormat() === $other->getDateFormat()
+               );
+       }
+
        /**
         * Registers a callback for tracking which ParserOptions which are used.
         * This is a private API with the parser.
@@ -784,7 +811,7 @@ class ParserOptions {
 
                // Give a chance for extensions to modify the hash, if they have
                // extra options or other effects on the parser cache.
-               wfRunHooks( 'PageRenderingHash', array( &$confstr, $this->getUser(), &$forOptions ) );
+               Hooks::run( 'PageRenderingHash', array( &$confstr, $this->getUser(), &$forOptions ) );
 
                // Make it a valid memcached key fragment
                $confstr = str_replace( ' ', '_', $confstr );
index b40519e..4ce88bd 100644 (file)
@@ -345,7 +345,9 @@ class ProfilerStandard extends Profiler {
                $this->close(); // set "-total" entry
 
                if ( $this->collateOnly ) {
-                       return; // already collated as methods exited
+                       // already collated as methods exited
+                       $this->sortCollated();
+                       return;
                }
 
                $this->collated = array();
@@ -400,7 +402,21 @@ class ProfilerStandard extends Profiler {
                }
 
                $this->collated['-overhead-total']['count'] = $profileCount;
-               arsort( $this->collated, SORT_NUMERIC );
+               $this->sortCollated();
+       }
+
+       protected function sortCollated() {
+               uksort( $this->collated, function ( $a, $b ) {
+                       $ca = $this->collated[$a]['real'];
+                       $cb = $this->collated[$b]['real'];
+                       if ( $ca > $cb ) {
+                               return -1;
+                       } elseif ( $cb > $ca ) {
+                               return 1;
+                       } else {
+                               return 0;
+                       }
+               } );
        }
 
        /**
index 5603aa5..a40c44a 100644 (file)
@@ -70,33 +70,12 @@ class ProfilerXhprof extends Profiler {
         */
        protected $sprofiler;
 
-       /**
-        * Type of report to send when logData() is called.
-        * @var string $logType
-        */
-       protected $logType;
-
-       /**
-        * Should profile report sent to in page content be visible?
-        * @var bool $visible
-        */
-       protected $visible;
-
        /**
         * @param array $params
         * @see Xhprof::__construct()
         */
        public function __construct( array $params = array() ) {
-               $params = array_merge(
-                       array(
-                               'log' => 'text',
-                               'visible' => false
-                       ),
-                       $params
-               );
                parent::__construct( $params );
-               $this->logType = $params['log'];
-               $this->visible = $params['visible'];
                $this->xhprof = new Xhprof( $params );
                $this->sprofiler = new SectionProfiler();
        }
index 275e986..2c36b68 100644 (file)
@@ -46,6 +46,8 @@ class SectionProfiler {
        protected $collateOnly = true;
        /** @var array Cache of a standard broken collation entry */
        protected $errorEntry;
+       /** @var callable Cache of a profile out callback */
+       protected $profileOutCallback;
 
        /**
         * @param array $params
@@ -53,6 +55,9 @@ class SectionProfiler {
        public function __construct( array $params = array() ) {
                $this->errorEntry = $this->getErrorEntry();
                $this->collateOnly = empty( $params['trace'] );
+               $this->profileOutCallback = function ( $profiler, $section ) {
+                       $profiler->profileOutInternal( $section );
+               };
        }
 
        /**
@@ -63,9 +68,7 @@ class SectionProfiler {
                $this->profileInInternal( $section );
 
                $that = $this;
-               return new ScopedCallback( function () use ( $that, $section ) {
-                       $that->profileOutInternal( $section );
-               } );
+               return new ScopedCallback( $this->profileOutCallback, array( $that, $section ) );
        }
 
        /**
index 02a8d7e..30be343 100644 (file)
@@ -56,7 +56,7 @@ class IRCColourfulRCFeedFormatter implements RCFeedFormatter {
                                $query .= '&rcid=' . $attribs['rc_id'];
                        }
                        // HACK: We need this hook for WMF's secure server setup
-                       wfRunHooks( 'IRCLineURL', array( &$url, &$query, $rc ) );
+                       Hooks::run( 'IRCLineURL', array( &$url, &$query, $rc ) );
                        $url .= $query;
                }
 
index 3f4e172..933397c 100644 (file)
@@ -63,8 +63,11 @@ class ResourceLoader {
         */
        protected $sources = array();
 
-       /** @var bool */
-       protected $hasErrors = false;
+       /**
+        * Errors accumulated during current respond() call.
+        * @var array
+        */
+       protected $errors = array();
 
        /**
         * Load information stored in the database about modules.
@@ -209,9 +212,7 @@ class ResourceLoader {
                } catch ( Exception $e ) {
                        MWExceptionHandler::logException( $e );
                        wfDebugLog( 'resourceloader', __METHOD__ . ": minification failed: $e" );
-                       $this->hasErrors = true;
-                       // Return exception as a comment
-                       $result = self::formatException( $e );
+                       $this->errors[] = self::formatExceptionNoComment( $e );
                }
 
                wfProfileOut( __METHOD__ );
@@ -246,7 +247,7 @@ class ResourceLoader {
                // Register core modules
                $this->register( include "$IP/resources/Resources.php" );
                // Register extension modules
-               wfRunHooks( 'ResourceLoaderRegisterModules', array( &$this ) );
+               Hooks::run( 'ResourceLoaderRegisterModules', array( &$this ) );
                $this->register( $config->get( 'ResourceModules' ) );
 
                if ( $config->get( 'EnableJavaScriptTest' ) === true ) {
@@ -376,7 +377,7 @@ class ResourceLoader {
                $testModules = array();
                $testModules['qunit'] = array();
                // Get other test suites (e.g. from extensions)
-               wfRunHooks( 'ResourceLoaderTestModules', array( &$testModules, &$this ) );
+               Hooks::run( 'ResourceLoaderTestModules', array( &$testModules, &$this ) );
 
                // Add the testrunner (which configures QUnit) to the dependencies.
                // Since it must be ready before any of the test suites are executed.
@@ -579,7 +580,6 @@ class ResourceLoader {
                ob_start();
 
                wfProfileIn( __METHOD__ );
-               $errors = '';
 
                // Find out which modules are missing and instantiate the others
                $modules = array();
@@ -591,10 +591,7 @@ class ResourceLoader {
                                // This is a security issue, see bug 34907.
                                if ( $module->getGroup() === 'private' ) {
                                        wfDebugLog( 'resourceloader', __METHOD__ . ": request for private module '$name' denied" );
-                                       $this->hasErrors = true;
-                                       // Add exception to the output as a comment
-                                       $errors .= self::makeComment( "Cannot show private module \"$name\"" );
-
+                                       $this->errors[] = "Cannot show private module \"$name\"";
                                        continue;
                                }
                                $modules[$name] = $module;
@@ -609,9 +606,7 @@ class ResourceLoader {
                } catch ( Exception $e ) {
                        MWExceptionHandler::logException( $e );
                        wfDebugLog( 'resourceloader', __METHOD__ . ": preloading module info failed: $e" );
-                       $this->hasErrors = true;
-                       // Add exception to the output as a comment
-                       $errors .= self::formatException( $e );
+                       $this->errors[] = self::formatExceptionNoComment( $e );
                }
 
                wfProfileIn( __METHOD__ . '-getModifiedTime' );
@@ -629,9 +624,7 @@ class ResourceLoader {
                        } catch ( Exception $e ) {
                                MWExceptionHandler::logException( $e );
                                wfDebugLog( 'resourceloader', __METHOD__ . ": calculating maximum modified time failed: $e" );
-                               $this->hasErrors = true;
-                               // Add exception to the output as a comment
-                               $errors .= self::formatException( $e );
+                               $this->errors[] = self::formatExceptionNoComment( $e );
                        }
                }
 
@@ -646,19 +639,15 @@ class ResourceLoader {
                // Generate a response
                $response = $this->makeModuleResponse( $context, $modules, $missing );
 
-               // Prepend comments indicating exceptions
-               $response = $errors . $response;
-
                // Capture any PHP warnings from the output buffer and append them to the
-               // response in a comment if we're in debug mode.
+               // error list if we're in debug mode.
                if ( $context->getDebug() && strlen( $warnings = ob_get_contents() ) ) {
-                       $response = self::makeComment( $warnings ) . $response;
-                       $this->hasErrors = true;
+                       $this->errors[] = $warnings;
                }
 
                // Save response to file cache unless there are errors
-               if ( isset( $fileCache ) && !$errors && !count( $missing ) ) {
-                       // Cache single modules...and other requests if there are enough hits
+               if ( isset( $fileCache ) && !$this->errors && !count( $missing ) ) {
+                       // Cache single modules and images...and other requests if there are enough hits
                        if ( ResourceFileCache::useFileCache( $context ) ) {
                                if ( $fileCache->isCacheWorthy() ) {
                                        $fileCache->saveText( $response );
@@ -669,10 +658,28 @@ class ResourceLoader {
                }
 
                // Send content type and cache related headers
-               $this->sendResponseHeaders( $context, $mtime, $this->hasErrors );
+               $this->sendResponseHeaders( $context, $mtime, (bool)$this->errors );
 
                // Remove the output buffer and output the response
                ob_end_clean();
+
+               if ( $context->getImageObj() && $this->errors ) {
+                       // We can't show both the error messages and the response when it's an image.
+                       $errorText = '';
+                       foreach ( $this->errors as $error ) {
+                               $errorText .= $error . "\n";
+                       }
+                       $response = $errorText;
+               } elseif ( $this->errors ) {
+                       // Prepend comments indicating errors
+                       $errorText = '';
+                       foreach ( $this->errors as $error ) {
+                               $errorText .= self::makeComment( $error );
+                       }
+                       $response = $errorText . $response;
+               }
+
+               $this->errors = array();
                echo $response;
 
                wfProfileOut( __METHOD__ );
@@ -682,7 +689,7 @@ class ResourceLoader {
         * Send content type and last modified headers to the client.
         * @param ResourceLoaderContext $context
         * @param string $mtime TS_MW timestamp to use for last-modified
-        * @param bool $errors Whether there are commented-out errors in the response
+        * @param bool $errors Whether there are errors in the response
         * @return void
         */
        protected function sendResponseHeaders( ResourceLoaderContext $context, $mtime, $errors ) {
@@ -699,7 +706,14 @@ class ResourceLoader {
                        $maxage = $rlMaxage['versioned']['client'];
                        $smaxage = $rlMaxage['versioned']['server'];
                }
-               if ( $context->getOnly() === 'styles' ) {
+               if ( $context->getImageObj() ) {
+                       // Output different headers if we're outputting textual errors.
+                       if ( $errors ) {
+                               header( 'Content-Type: text/plain; charset=utf-8' );
+                       } else {
+                               $context->getImageObj()->sendResponseHeaders( $context );
+                       }
+               } elseif ( $context->getOnly() === 'styles' ) {
                        header( 'Content-Type: text/css; charset=utf-8' );
                        header( 'Access-Control-Allow-Origin: *' );
                } else {
@@ -823,15 +837,26 @@ class ResourceLoader {
         * Handle exception display.
         *
         * @param Exception $e Exception to be shown to the user
-        * @return string Sanitized text that can be returned to the user
+        * @return string Sanitized text in a CSS/JS comment that can be returned to the user
         */
        public static function formatException( $e ) {
+               return self::makeComment( self::formatExceptionNoComment( $e ) );
+       }
+
+       /**
+        * Handle exception display.
+        *
+        * @since 1.25
+        * @param Exception $e Exception to be shown to the user
+        * @return string Sanitized text that can be returned to the user
+        */
+       protected static function formatExceptionNoComment( $e ) {
                global $wgShowExceptionDetails;
 
                if ( $wgShowExceptionDetails ) {
-                       return self::makeComment( $e->__toString() );
+                       return $e->__toString();
                } else {
-                       return self::makeComment( wfMessage( 'internalerror' )->text() );
+                       return wfMessage( 'internalerror' )->text();
                }
        }
 
@@ -847,7 +872,6 @@ class ResourceLoader {
                array $modules, array $missing = array()
        ) {
                $out = '';
-               $exceptions = '';
                $states = array();
 
                if ( !count( $modules ) && !count( $missing ) ) {
@@ -858,6 +882,17 @@ class ResourceLoader {
 
                wfProfileIn( __METHOD__ );
 
+               $image = $context->getImageObj();
+               if ( $image ) {
+                       $data = $image->getImageData( $context );
+                       if ( $data === false ) {
+                               $data = '';
+                               $this->errors[] = 'Image generation failed';
+                       }
+                       wfProfileOut( __METHOD__ );
+                       return $data;
+               }
+
                // Pre-fetch blobs
                if ( $context->shouldIncludeMessages() ) {
                        try {
@@ -868,9 +903,7 @@ class ResourceLoader {
                                        'resourceloader',
                                        __METHOD__ . ": pre-fetching blobs from MessageBlobStore failed: $e"
                                );
-                               $this->hasErrors = true;
-                               // Add exception to the output as a comment
-                               $exceptions .= self::formatException( $e );
+                               $this->errors[] = self::formatExceptionNoComment( $e );
                        }
                } else {
                        $blobs = array();
@@ -994,9 +1027,7 @@ class ResourceLoader {
                        } catch ( Exception $e ) {
                                MWExceptionHandler::logException( $e );
                                wfDebugLog( 'resourceloader', __METHOD__ . ": generating module package failed: $e" );
-                               $this->hasErrors = true;
-                               // Add exception to the output as a comment
-                               $exceptions .= self::formatException( $e );
+                               $this->errors[] = self::formatExceptionNoComment( $e );
 
                                // Respond to client with error-state instead of module implementation
                                $states[$name] = 'error';
@@ -1022,9 +1053,8 @@ class ResourceLoader {
                        }
                } else {
                        if ( count( $states ) ) {
-                               $exceptions .= self::makeComment(
-                                       'Problematic modules: ' . FormatJson::encode( $states, ResourceLoader::inDebugMode() )
-                               );
+                               $this->errors[] = 'Problematic modules: ' .
+                                       FormatJson::encode( $states, ResourceLoader::inDebugMode() );
                        }
                }
 
@@ -1037,7 +1067,7 @@ class ResourceLoader {
                }
 
                wfProfileOut( __METHOD__ );
-               return $exceptions . $out;
+               return $out;
        }
 
        /* Static Methods */
index 02744a6..a6a7d34 100644 (file)
@@ -41,7 +41,11 @@ class ResourceLoaderContext {
        protected $version;
        protected $hash;
        protected $raw;
+       protected $image;
+       protected $variant;
+       protected $format;
        protected $userObj;
+       protected $imageObj;
 
        /* Methods */
 
@@ -66,6 +70,10 @@ class ResourceLoaderContext {
                $this->only = $request->getVal( 'only' );
                $this->version = $request->getVal( 'version' );
                $this->raw = $request->getFuzzyBool( 'raw' );
+               // Image requests
+               $this->image = $request->getVal( 'image' );
+               $this->variant = $request->getVal( 'variant' );
+               $this->format = $request->getVal( 'format' );
 
                $skinnames = Skin::getSkinNames();
                // If no skin is specified, or we don't recognize the skin, use the default skin
@@ -232,6 +240,62 @@ class ResourceLoaderContext {
                return $this->raw;
        }
 
+       /**
+        * @return string|null
+        */
+       public function getImage() {
+               return $this->image;
+       }
+
+       /**
+        * @return string|null
+        */
+       public function getVariant() {
+               return $this->variant;
+       }
+
+       /**
+        * @return string|null
+        */
+       public function getFormat() {
+               return $this->format;
+       }
+
+       /**
+        * If this is a request for an image, get the ResourceLoaderImage object.
+        *
+        * @since 1.25
+        * @return ResourceLoaderImage|bool false if a valid object cannot be created
+        */
+       public function getImageObj() {
+               if ( $this->imageObj === null ) {
+                       $this->imageObj = false;
+
+                       if ( !$this->image ) {
+                               return $this->imageObj;
+                       }
+
+                       $modules = $this->getModules();
+                       if ( count( $modules ) !== 1 ) {
+                               return $this->imageObj;
+                       }
+
+                       $module = $this->getResourceLoader()->getModule( $modules[0] );
+                       if ( !$module || !$module instanceof ResourceLoaderImageModule ) {
+                               return $this->imageObj;
+                       }
+
+                       $image = $module->getImage( $this->image );
+                       if ( !$image ) {
+                               return $this->imageObj;
+                       }
+
+                       $this->imageObj = $image;
+               }
+
+               return $this->imageObj;
+       }
+
        /**
         * @return bool
         */
@@ -260,6 +324,7 @@ class ResourceLoaderContext {
                if ( !isset( $this->hash ) ) {
                        $this->hash = implode( '|', array(
                                $this->getLanguage(), $this->getDirection(), $this->getSkin(), $this->getUser(),
+                               $this->getImage(), $this->getVariant(), $this->getFormat(),
                                $this->getDebug(), $this->getOnly(), $this->getVersion()
                        ) );
                }
diff --git a/includes/resourceloader/ResourceLoaderImage.php b/includes/resourceloader/ResourceLoaderImage.php
new file mode 100644 (file)
index 0000000..0e43f65
--- /dev/null
@@ -0,0 +1,356 @@
+<?php
+/**
+ * Class encapsulating an image used in a ResourceLoaderImageModule.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Class encapsulating an image used in a ResourceLoaderImageModule.
+ *
+ * @since 1.25
+ */
+class ResourceLoaderImage {
+
+       /**
+        * Map of allowed file extensions to their MIME types.
+        * @var array
+        */
+       protected static $fileTypes = array(
+               'svg' => 'image/svg+xml',
+               'png' => 'image/png',
+               'gif' => 'image/gif',
+               'jpg' => 'image/jpg',
+       );
+
+       /**
+        * @param string $name Image name
+        * @param string $module Module name
+        * @param string|array $descriptor Path to image file, or array structure containing paths
+        * @param string $basePath Directory to which paths in descriptor refer
+        * @param array $variants
+        * @throws MWException
+        */
+       public function __construct( $name, $module, $descriptor, $basePath, $variants ) {
+               $this->name = $name;
+               $this->module = $module;
+               $this->descriptor = $descriptor;
+               $this->basePath = $basePath;
+               $this->variants = $variants;
+
+               // Ensure that all files have common extension.
+               $extensions = array();
+               $descriptor = (array)$descriptor;
+               array_walk_recursive( $descriptor, function ( $path ) use ( &$extensions ) {
+                       $extensions[] = pathinfo( $path, PATHINFO_EXTENSION );
+               } );
+               $extensions = array_unique( $extensions );
+               if ( count( $extensions ) !== 1 ) {
+                       throw new MWException( 'Image type for various images differs.' );
+               }
+               $ext = $extensions[0];
+               if ( !isset( self::$fileTypes[$ext] ) ) {
+                       throw new MWException( 'Invalid image type; svg, png, gif or jpg required.' );
+               }
+               $this->extension = $ext;
+       }
+
+       /**
+        * Get name of this image.
+        *
+        * @return string
+        */
+       public function getName() {
+               return $this->name;
+       }
+
+       /**
+        * Get name of the module this image belongs to.
+        *
+        * @return string
+        */
+       public function getModule() {
+               return $this->module;
+       }
+
+       /**
+        * Get the list of variants this image can be converted to.
+        *
+        * @return string[]
+        */
+       public function getVariants() {
+               return array_keys( $this->variants );
+       }
+
+       /**
+        * Get the path to image file for given context.
+        *
+        * @param ResourceLoaderContext $context Any context
+        * @return string
+        */
+       protected function getPath( ResourceLoaderContext $context ) {
+               $desc = $this->descriptor;
+               if ( is_string( $desc ) ) {
+                       return $this->basePath . '/' . $desc;
+               } elseif ( isset( $desc['lang'][ $context->getLanguage() ] ) ) {
+                       return $this->basePath . '/' . $desc['lang'][ $context->getLanguage() ];
+               } elseif ( isset( $desc[ $context->getDirection() ] ) ) {
+                       return $this->basePath . '/' . $desc[ $context->getDirection() ];
+               } else {
+                       return $this->basePath . '/' . $desc['default'];
+               }
+       }
+
+       /**
+        * Get the extension of the image.
+        *
+        * @param string $format Format to get the extension for, 'original' or 'rasterized'
+        * @return string Extension without leading dot, e.g. 'png'
+        */
+       public function getExtension( $format = 'original' ) {
+               if ( $format === 'rasterized' && $this->extension === 'svg' ) {
+                       return 'png';
+               } else {
+                       return $this->extension;
+               }
+       }
+
+       /**
+        * Get the MIME type of the image.
+        *
+        * @param string $format Format to get the MIME type for, 'original' or 'rasterized'
+        * @return string
+        */
+       public function getMimeType( $format = 'original' ) {
+               $ext = $this->getExtension( $format );
+               return self::$fileTypes[$ext];
+       }
+
+       /**
+        * Get the load.php URL that will produce this image.
+        *
+        * @param ResourceLoaderContext $context Any context
+        * @param string $script URL to load.php
+        * @param string|null $variant Variant to get the URL for
+        * @param string $format Format to get the URL for, 'original' or 'rasterized'
+        * @return string
+        */
+       public function getUrl( ResourceLoaderContext $context, $script, $variant, $format ) {
+               $query = array(
+                       'modules' => $this->getModule(),
+                       'image' => $this->getName(),
+                       'variant' => $variant,
+                       'format' => $format,
+                       'lang' => $context->getLanguage(),
+                       'version' => $context->getVersion(),
+               );
+
+               return wfExpandUrl( wfAppendQuery( $script, $query ), PROTO_RELATIVE );
+       }
+
+       /**
+        * Get the data: URI that will produce this image.
+        *
+        * @param ResourceLoaderContext $context Any context
+        * @param string|null $variant Variant to get the URI for
+        * @param string $format Format to get the URI for, 'original' or 'rasterized'
+        * @return string
+        */
+       public function getDataUri( ResourceLoaderContext $context, $variant, $format ) {
+               $type = $this->getMimeType( $format );
+               $contents = $this->getImageData( $context, $variant, $format );
+               return CSSMin::encodeStringAsDataURI( $contents, $type );
+       }
+
+       /**
+        * Get actual image data for this image. This can be saved to a file or sent to the browser to
+        * produce the converted image.
+        *
+        * Call getExtension() or getMimeType() with the same $format argument to learn what file type the
+        * returned data uses.
+        *
+        * @param ResourceLoaderContext $context Image context, or any context of $variant and $format
+        *     given.
+        * @param string|null $variant Variant to get the data for. Optional, if given, overrides the data
+        *     from $context.
+        * @param string $format Format to get the data for, 'original' or 'rasterized'. Optional, if
+        *     given, overrides the data from $context.
+        * @return string|false Possibly binary image data, or false on failure
+        */
+       public function getImageData( ResourceLoaderContext $context, $variant = false, $format = false ) {
+               if ( $variant === false ) {
+                       $variant = $context->getVariant();
+               }
+               if ( $format === false ) {
+                       $format = $context->getFormat();
+               }
+
+               if ( $this->getExtension() !== 'svg' ) {
+                       return file_get_contents( $this->getPath( $context ) );
+               }
+
+               if ( $variant && isset( $this->variants[$variant] ) ) {
+                       $data = $this->variantize( $this->variants[$variant], $context );
+               } else {
+                       $data = file_get_contents( $this->getPath( $context ) );
+               }
+
+               if ( $format === 'rasterized' ) {
+                       $data = $this->rasterize( $data );
+               }
+
+               return $data;
+       }
+
+       /**
+        * Send response headers (using the header() function) that are necessary to correctly serve the
+        * image data for this image, as returned by getImageData().
+        *
+        * Note that the headers are independent of the language or image variant.
+        *
+        * @param ResourceLoaderContext $context Image context
+        */
+       public function sendResponseHeaders( ResourceLoaderContext $context ) {
+               $format = $context->getFormat();
+               $mime = $this->getMimeType( $format );
+               $filename = $this->getName() . '.' . $this->getExtension( $format );
+
+               header( 'Content-Type: ' . $mime );
+               header( 'Content-Disposition: ' .
+                       FileBackend::makeContentDisposition( 'inline', $filename ) );
+       }
+
+       /**
+        * Convert this image, which is assumed to be SVG, to given variant.
+        *
+        * @param array $variantConf Array with a 'color' key, its value will be used as fill color
+        * @param ResourceLoaderContext $context Image context
+        * @return string New SVG file data
+        */
+       protected function variantize( $variantConf, ResourceLoaderContext $context ) {
+               $dom = new DomDocument;
+               $dom->load( $this->getPath( $context ) );
+               $root = $dom->documentElement;
+               $wrapper = $dom->createElement( 'g' );
+               while ( $root->firstChild ) {
+                       $wrapper->appendChild( $root->firstChild );
+               }
+               $root->appendChild( $wrapper );
+               $wrapper->setAttribute( 'fill', $variantConf['color'] );
+               return $dom->saveXml();
+       }
+
+       /**
+        * Massage the SVG image data for converters which doesn't understand some path data syntax.
+        *
+        * This is necessary for rsvg and ImageMagick when compiled with rsvg support.
+        * Upstream bug is https://bugzilla.gnome.org/show_bug.cgi?id=620923, fixed 2014-11-10, so
+        * this will be needed for a while. (T76852)
+        *
+        * @param string $svg SVG image data
+        * @return string Massaged SVG image data
+        */
+       protected function massageSvgPathdata( $svg ) {
+               $dom = new DomDocument;
+               $dom->loadXml( $svg );
+               foreach ( $dom->getElementsByTagName( 'path' ) as $node ) {
+                       $pathData = $node->getAttribute( 'd' );
+                       // Make sure there is at least one space between numbers, and that leading zero is not omitted.
+                       // rsvg has issues with syntax like "M-1-2" and "M.445.483" and especially "M-.445-.483".
+                       $pathData = preg_replace( '/(-?)(\d*\.\d+|\d+)/', ' ${1}0$2 ', $pathData );
+                       // Strip unnecessary leading zeroes for prettiness, not strictly necessary
+                       $pathData = preg_replace( '/([ -])0(\d)/', '$1$2', $pathData );
+                       $node->setAttribute( 'd', $pathData );
+               }
+               return $dom->saveXml();
+       }
+
+       /**
+        * Convert passed image data, which is assumed to be SVG, to PNG.
+        *
+        * @param string $svg SVG image data
+        * @return string|bool PNG image data, or false on failure
+        */
+       protected function rasterize( $svg ) {
+               // This code should be factored out to a separate method on SvgHandler, or perhaps a separate
+               // class, with a separate set of configuration settings.
+               //
+               // This is a distinct use case from regular SVG rasterization:
+               // * we can skip many sanity and security checks (as the images come from a trusted source,
+               //   rather than from the user)
+               // * we need to provide extra options to some converters to achieve acceptable quality for very
+               //   small images, which might cause performance issues in the general case
+               // * we need to directly pass image data to the converter instead of a file path
+               //
+               // See https://phabricator.wikimedia.org/T76473#801446 for examples of what happens with the
+               // default settings.
+               //
+               // For now, we special-case rsvg (used in WMF production) and do a messy workaround for other
+               // converters.
+
+               global $wgSVGConverter, $wgSVGConverterPath;
+
+               $svg = $this->massageSvgPathdata( $svg );
+
+               if ( $wgSVGConverter === 'rsvg' ) {
+                       $command = 'rsvg-convert'; // Should be just 'rsvg'? T76476
+                       if ( $wgSVGConverterPath ) {
+                               $command = wfEscapeShellArg( "$wgSVGConverterPath/" ) . $command;
+                       }
+
+                       $process = proc_open(
+                               $command,
+                               array( 0 => array( 'pipe', 'r' ), 1 => array( 'pipe', 'w' ) ),
+                               $pipes
+                       );
+
+                       if ( is_resource( $process ) ) {
+                               fwrite( $pipes[0], $svg );
+                               fclose( $pipes[0] );
+                               $png = stream_get_contents( $pipes[1] );
+                               fclose( $pipes[1] );
+                               proc_close( $process );
+
+                               return $png ?: false;
+                       }
+                       return false;
+
+               } else {
+                       // Write input to and read output from a temporary file
+                       $tempFilenameSvg = tempnam( wfTempDir(), 'ResourceLoaderImage' );
+                       $tempFilenamePng = tempnam( wfTempDir(), 'ResourceLoaderImage' );
+
+                       file_put_contents( $tempFilenameSvg, $svg );
+
+                       $metadata = SVGMetadataExtractor::getMetadata( $tempFilenameSvg );
+                       if ( !isset( $metadata['width'] ) || !isset( $metadata['height'] ) ) {
+                               return false;
+                       }
+
+                       $handler = new SvgHandler;
+                       $handler->rasterize( $tempFilenameSvg, $tempFilenamePng, $metadata['width'], $metadata['height'] );
+
+                       $png = file_get_contents( $tempFilenamePng );
+
+                       unlink( $tempFilenameSvg );
+                       unlink( $tempFilenamePng );
+
+                       return $png ?: false;
+               }
+       }
+}
diff --git a/includes/resourceloader/ResourceLoaderImageModule.php b/includes/resourceloader/ResourceLoaderImageModule.php
new file mode 100644 (file)
index 0000000..9246df7
--- /dev/null
@@ -0,0 +1,295 @@
+<?php
+/**
+ * Resource loader module for generated and embedded images.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Trevor Parscal
+ */
+
+/**
+ * Resource loader module for generated and embedded images.
+ *
+ * @since 1.25
+ */
+class ResourceLoaderImageModule extends ResourceLoaderModule {
+
+       /**
+        * Local base path, see __construct()
+        * @var string
+        */
+       protected $localBasePath = '';
+
+       protected $origin = self::ORIGIN_CORE_SITEWIDE;
+
+       protected $images = array();
+       protected $variants = array();
+       protected $prefix = array();
+       protected $targets = array( 'desktop', 'mobile' );
+
+       /**
+        * Constructs a new module from an options array.
+        *
+        * @param array $options List of options; if not given or empty, an empty module will be
+        *     constructed
+        * @param string $localBasePath Base path to prepend to all local paths in $options. Defaults
+        *     to $IP
+        *
+        * Below is a description for the $options array:
+        * @par Construction options:
+        * @code
+        *     array(
+        *         // Base path to prepend to all local paths in $options. Defaults to $IP
+        *         'localBasePath' => [base path],
+        *         // CSS class prefix to use in all style rules
+        *         'prefix' => [CSS class prefix],
+        *         // List of variants that may be used for the image files
+        *         'variants' => array(
+        *             // ([image type] is a string, used in generated CSS class names and to match variants to images)
+        *             [image type] => array(
+        *                 [variant name] => array(
+        *                     'color' => [color string, e.g. '#ffff00'],
+        *                     'global' => [boolean, if true, this variant is available for all images of this type],
+        *                 ),
+        *             )
+        *         ),
+        *         // List of image files and their options
+        *         'images' => array(
+        *             [image type] => array(
+        *                 [file path string],
+        *                 [file path string] => array(
+        *                     'name' => [image name string, defaults to file name],
+        *                     'variants' => [array of variant name strings, variants available for this image],
+        *                 ),
+        *             )
+        *         ),
+        *     )
+        * @endcode
+        * @throws MWException
+        */
+       public function __construct( $options = array(), $localBasePath = null ) {
+               $this->localBasePath = self::extractLocalBasePath( $options, $localBasePath );
+
+               if ( !isset( $options['prefix'] ) || !$options['prefix'] ) {
+                       throw new MWException(
+                               "Required 'prefix' option not given or empty."
+                       );
+               }
+
+               foreach ( $options as $member => $option ) {
+                       switch ( $member ) {
+                               case 'images':
+                                       if ( !is_array( $option ) ) {
+                                               throw new MWException(
+                                                       "Invalid collated file path list error. '$option' given, array expected."
+                                               );
+                                       }
+                                       foreach ( $option as $key => $value ) {
+                                               if ( !is_string( $key ) ) {
+                                                       throw new MWException(
+                                                               "Invalid collated file path list key error. '$key' given, string expected."
+                                                       );
+                                               }
+                                               $this->{$member}[$key] = (array)$value;
+                                       }
+                                       break;
+
+                               case 'variants':
+                                       if ( !is_array( $option ) ) {
+                                               throw new MWException(
+                                                       "Invalid variant list error. '$option' given, array expected."
+                                               );
+                                       }
+                                       $this->{$member} = $option;
+                                       break;
+
+                               case 'prefix':
+                                       $this->{$member} = (string)$option;
+                                       break;
+                       }
+               }
+       }
+
+       /**
+        * Get CSS class prefix used by this module.
+        * @return string
+        */
+       public function getPrefix() {
+               return $this->prefix;
+       }
+
+       /**
+        * Get a ResourceLoaderImage object for given image.
+        * @param string $name Image name
+        * @return ResourceLoaderImage|null
+        */
+       public function getImage( $name ) {
+               $images = $this->getImages();
+               return isset( $images[$name] ) ? $images[$name] : null;
+       }
+
+       /**
+        * Get ResourceLoaderImage objects for all images.
+        * @return ResourceLoaderImage[] Array keyed by image name
+        */
+       public function getImages() {
+               if ( !isset( $this->imageObjects ) ) {
+                       $this->imageObjects = array();
+
+                       foreach ( $this->images as $type => $list ) {
+                               foreach ( $list as $name => $options ) {
+                                       $imageDesc = is_string( $options ) ? $options : $options['image'];
+
+                                       $allowedVariants = array_merge(
+                                               isset( $options['variants'] ) ? $options['variants'] : array(),
+                                               $this->getGlobalVariants( $type )
+                                       );
+                                       $variantConfig = array_intersect_key(
+                                               $this->variants[$type],
+                                               array_fill_keys( $allowedVariants, true )
+                                       );
+
+                                       $image = new ResourceLoaderImage( $name, $this->getName(), $imageDesc, $this->localBasePath, $variantConfig );
+                                       $this->imageObjects[ $image->getName() ] = $image;
+                               }
+                       }
+               }
+
+               return $this->imageObjects;
+       }
+
+       /**
+        * Get list of variants in this module that are 'global' for given type of images, i.e., available
+        * for every image of given type regardless of image options.
+        * @param string $type Image type
+        * @return string[]
+        */
+       public function getGlobalVariants( $type ) {
+               if ( !isset( $this->globalVariants[$type] ) ) {
+                       $this->globalVariants[$type] = array();
+
+                       foreach ( $this->variants[$type] as $name => $config ) {
+                               if ( isset( $config['global'] ) && $config['global'] ) {
+                                       $this->globalVariants[$type][] = $name;
+                               }
+                       }
+               }
+
+               return $this->globalVariants[$type];
+       }
+
+       /**
+        * Get the type of given image.
+        * @param string $imageName Image name
+        * @return string
+        */
+       public function getImageType( $imageName ) {
+               foreach ( $this->images as $type => $list ) {
+                       foreach ( $list as $key => $value ) {
+                               $file = is_int( $key ) ? $value : $key;
+                               $options = is_array( $value ) ? $value : array();
+                               $name = isset( $options['name'] ) ? $options['name'] : pathinfo( $file, PATHINFO_FILENAME );
+                               if ( $name === $imageName ) {
+                                       return $type;
+                               }
+                       }
+               }
+       }
+
+       /**
+        * @param ResourceLoaderContext $context
+        * @return array
+        */
+       public function getStyles( ResourceLoaderContext $context ) {
+               // Build CSS rules
+               $rules = array();
+               $script = $context->getResourceLoader()->getLoadScript( $this->getSource() );
+               $prefix = $this->getPrefix();
+
+               foreach ( $this->getImages() as $name => $image ) {
+                       $type = $this->getImageType( $name );
+
+                       $declarations = $this->getCssDeclarations(
+                               $image->getDataUri( $context, null, 'original' ),
+                               $image->getUrl( $context, $script, null, 'rasterized' )
+                       );
+                       $declarations = implode( "\n\t", $declarations );
+                       $rules[] = ".$prefix-$type-$name {\n\t$declarations\n}";
+
+                       // TODO: Get variant configurations from $context->getSkin()
+                       foreach ( $image->getVariants() as $variant ) {
+                               $declarations = $this->getCssDeclarations(
+                                       $image->getDataUri( $context, $variant, 'original' ),
+                                       $image->getUrl( $context, $script, $variant, 'rasterized' )
+                               );
+                               $declarations = implode( "\n\t", $declarations );
+                               $rules[] = ".$prefix-$type-$name-$variant {\n\t$declarations\n}";
+                       }
+               }
+
+               $style = implode( "\n", $rules );
+               if ( $this->getFlip( $context ) ) {
+                       $style = CSSJanus::transform( $style, true, false );
+               }
+               return array( 'all' => $style );
+       }
+
+       /**
+        * @param string $primary Primary URI
+        * @param string $fallback Fallback URI
+        * @return string[] CSS declarations to use given URIs as background-image
+        */
+       protected function getCssDeclarations( $primary, $fallback ) {
+               // SVG support using a transparent gradient to guarantee cross-browser
+               // compatibility (browsers able to understand gradient syntax support also SVG).
+               // http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique
+               return array(
+                       "background-image: url($fallback);",
+                       "background-image: -webkit-linear-gradient(transparent, transparent), url($primary);",
+                       "background-image: linear-gradient(transparent, transparent), url($primary);",
+               );
+       }
+
+       /**
+        * @return bool
+        */
+       public function supportsURLLoading() {
+               return false;
+       }
+
+       /**
+        * Extract a local base path from module definition information.
+        *
+        * @param array $options Module definition
+        * @param string $localBasePath Path to use if not provided in module definition. Defaults
+        *     to $IP
+        * @return string Local base path
+        */
+       public static function extractLocalBasePath( $options, $localBasePath = null ) {
+               global $IP;
+
+               if ( $localBasePath === null ) {
+                       $localBasePath = $IP;
+               }
+
+               if ( array_key_exists( 'localBasePath', $options ) ) {
+                       $localBasePath = (string)$options['localBasePath'];
+               }
+
+               return $localBasePath;
+       }
+}
index 6de1be0..9835932 100644 (file)
@@ -41,7 +41,7 @@ class ResourceLoaderSkinModule extends ResourceLoaderFileModule {
 
        /**
         * @param $context ResourceLoaderContext
-        * @return boolean
+        * @return bool
         */
        public function isKnownEmpty( ResourceLoaderContext $context ) {
                // Regardless of whether the files are specified, we always
index 2eccf81..a0764de 100644 (file)
@@ -106,7 +106,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        'wgResourceLoaderStorageEnabled' => $conf->get( 'ResourceLoaderStorageEnabled' ),
                );
 
-               wfRunHooks( 'ResourceLoaderGetConfigVars', array( &$vars ) );
+               Hooks::run( 'ResourceLoaderGetConfigVars', array( &$vars ) );
 
                $this->configVars[$hash] = $vars;
                return $this->configVars[$hash];
index e7aed73..6ae0afc 100644 (file)
@@ -32,7 +32,7 @@ class RevDelArchiveList extends RevDelRevisionList {
        }
 
        /**
-        * @param DatabaseBase $db
+        * @param IDatabase $db
         * @return mixed
         */
        public function doQuery( $db ) {
index aec51b1..f2b99ae 100644 (file)
@@ -32,7 +32,7 @@ class RevDelArchivedFileList extends RevDelFileList {
        }
 
        /**
-        * @param DatabaseBase $db
+        * @param IDatabase $db
         * @return mixed
         */
        public function doQuery( $db ) {
index 57e15d8..2295eaa 100644 (file)
@@ -49,7 +49,7 @@ class RevDelFileList extends RevDelList {
        }
 
        /**
-        * @param DatabaseBase $db
+        * @param IDatabase $db
         * @return mixed
         */
        public function doQuery( $db ) {
index ad04042..86c5af3 100644 (file)
@@ -55,7 +55,7 @@ class RevDelLogList extends RevDelList {
        }
 
        /**
-        * @param DatabaseBase $db
+        * @param IDatabase $db
         * @return mixed
         */
        public function doQuery( $db ) {
index 2545072..7315538 100644 (file)
@@ -54,7 +54,7 @@ class RevDelRevisionList extends RevDelList {
        }
 
        /**
-        * @param DatabaseBase $db
+        * @param IDatabase $db
         * @return mixed
         */
        public function doQuery( $db ) {
@@ -137,7 +137,7 @@ class RevDelRevisionList extends RevDelList {
        public function doPostCommitUpdates() {
                $this->title->purgeSquid();
                // Extensions that require referencing previous revisions may need this
-               wfRunHooks( 'ArticleRevisionVisibilitySet', array( &$this->title ) );
+               Hooks::run( 'ArticleRevisionVisibilitySet', array( &$this->title ) );
                return Status::newGood();
        }
 }
index 55c46c5..79802d6 100644 (file)
@@ -36,14 +36,14 @@ class RevisionDeleteUser {
         * @param string $name Username
         * @param int $userId User id
         * @param string $op Operator '|' or '&'
-        * @param null|DatabaseBase $dbw If you happen to have one lying around
+        * @param null|IDatabase $dbw If you happen to have one lying around
         * @return bool
         */
        private static function setUsernameBitfields( $name, $userId, $op, $dbw ) {
                if ( !$userId || ( $op !== '|' && $op !== '&' ) ) {
                        return false; // sanity check
                }
-               if ( !$dbw instanceof DatabaseBase ) {
+               if ( !$dbw instanceof IDatabase ) {
                        $dbw = wfGetDB( DB_MASTER );
                }
 
index c6cbfbe..cd6cf7d 100644 (file)
@@ -137,7 +137,7 @@ class SearchEngine {
        public static function getNearMatch( $searchterm ) {
                $title = self::getNearMatchInternal( $searchterm );
 
-               wfRunHooks( 'SearchGetNearMatchComplete', array( $searchterm, &$title ) );
+               Hooks::run( 'SearchGetNearMatchComplete', array( $searchterm, &$title ) );
                return $title;
        }
 
@@ -170,7 +170,7 @@ class SearchEngine {
                }
 
                $titleResult = null;
-               if ( !wfRunHooks( 'SearchGetNearMatchBefore', array( $allSearchTerms, &$titleResult ) ) ) {
+               if ( !Hooks::run( 'SearchGetNearMatchBefore', array( $allSearchTerms, &$titleResult ) ) ) {
                        return $titleResult;
                }
 
@@ -197,7 +197,7 @@ class SearchEngine {
                                return $title;
                        }
 
-                       if ( !wfRunHooks( 'SearchAfterNoDirectMatch', array( $term, &$title ) ) ) {
+                       if ( !Hooks::run( 'SearchAfterNoDirectMatch', array( $term, &$title ) ) ) {
                                return $title;
                        }
 
@@ -227,7 +227,7 @@ class SearchEngine {
 
                        // Give hooks a chance at better match variants
                        $title = null;
-                       if ( !wfRunHooks( 'SearchGetNearMatch', array( $term, &$title ) ) ) {
+                       if ( !Hooks::run( 'SearchGetNearMatch', array( $term, &$title ) ) ) {
                                return $title;
                        }
                }
@@ -356,7 +356,7 @@ class SearchEngine {
                        }
                }
 
-               wfRunHooks( 'SearchableNamespaces', array( &$arr ) );
+               Hooks::run( 'SearchableNamespaces', array( &$arr ) );
                return $arr;
        }
 
index 2cdf9f4..d384ae9 100644 (file)
@@ -71,7 +71,7 @@ class SearchResult {
                $this->mTitle = $title;
                if ( !is_null( $this->mTitle ) ) {
                        $id = false;
-                       wfRunHooks( 'SearchResultInitFromTitle', array( $title, &$id ) );
+                       Hooks::run( 'SearchResultInitFromTitle', array( $title, &$id ) );
                        $this->mRevision = Revision::newFromTitle(
                                $this->mTitle, $id, Revision::READ_NORMAL );
                        if ( $this->mTitle->getNamespace() === NS_FILE ) {
index 7217000..3cdfca0 100644 (file)
@@ -112,7 +112,7 @@ abstract class BaseTemplate extends QuickTemplate {
                        $toolbox['info']['id'] = 't-info';
                }
 
-               wfRunHooks( 'BaseTemplateToolbox', array( &$this, &$toolbox ) );
+               Hooks::run( 'BaseTemplateToolbox', array( &$this, &$toolbox ) );
                wfProfileOut( __METHOD__ );
                return $toolbox;
        }
@@ -228,7 +228,7 @@ abstract class BaseTemplate extends QuickTemplate {
                        ob_start();
                        // We pass an extra 'true' at the end so extensions using BaseTemplateToolbox
                        // can abort and avoid outputting double toolbox links
-                       wfRunHooks( 'SkinTemplateToolboxEnd', array( &$this, true ) );
+                       Hooks::run( 'SkinTemplateToolboxEnd', array( &$this, true ) );
                        $hookContents = ob_get_contents();
                        ob_end_clean();
                        if ( !trim( $hookContents ) ) {
@@ -285,7 +285,7 @@ abstract class BaseTemplate extends QuickTemplate {
         */
        protected function renderAfterPortlet( $name ) {
                $content = '';
-               wfRunHooks( 'BaseTemplateAfterPortlet', array( $this, $name, &$content ) );
+               Hooks::run( 'BaseTemplateAfterPortlet', array( $this, $name, &$content ) );
 
                if ( $content !== '' ) {
                        echo "<div class='after-portlet after-portlet-$name'>$content</div>";
index 5604bc2..ce0c640 100644 (file)
@@ -259,7 +259,7 @@ abstract class Skin extends ContextSource {
                        $titles[] = $title->getTalkPage();
                }
 
-               wfRunHooks( 'SkinPreloadExistence', array( &$titles, $this ) );
+               Hooks::run( 'SkinPreloadExistence', array( &$titles, $this ) );
 
                if ( count( $titles ) ) {
                        $lb = new LinkBatch( $titles );
@@ -587,7 +587,7 @@ abstract class Skin extends ContextSource {
        protected function afterContentHook() {
                $data = '';
 
-               if ( wfRunHooks( 'SkinAfterContent', array( &$data, $this ) ) ) {
+               if ( Hooks::run( 'SkinAfterContent', array( &$data, $this ) ) ) {
                        // adding just some spaces shouldn't toggle the output
                        // of the whole <div/>, so we use trim() here
                        if ( trim( $data ) != '' ) {
@@ -624,7 +624,7 @@ abstract class Skin extends ContextSource {
                // OutputPage::getBottomScripts() which takes a Skin param. This should be cleaned
                // up at some point
                $bottomScriptText = $this->getOutput()->getBottomScripts();
-               wfRunHooks( 'SkinAfterBottomScripts', array( $this, &$bottomScriptText ) );
+               Hooks::run( 'SkinAfterBottomScripts', array( $this, &$bottomScriptText ) );
 
                return $bottomScriptText;
        }
@@ -684,7 +684,7 @@ abstract class Skin extends ContextSource {
                $out = $this->getOutput();
                $subpages = '';
 
-               if ( !wfRunHooks( 'SkinSubPageSubtitle', array( &$subpages, $this, $out ) ) ) {
+               if ( !Hooks::run( 'SkinSubPageSubtitle', array( &$subpages, $this, $out ) ) ) {
                        return $subpages;
                }
 
@@ -793,7 +793,7 @@ abstract class Skin extends ContextSource {
                // @todo Remove deprecated $forContent param from hook handlers and then remove here.
                $forContent = true;
 
-               wfRunHooks(
+               Hooks::run(
                        'SkinCopyrightFooter',
                        array( $this->getTitle(), $type, &$msg, &$link, &$forContent )
                );
@@ -840,7 +840,7 @@ abstract class Skin extends ContextSource {
                $url = htmlspecialchars( "$wgResourceBasePath/resources/assets/poweredby_mediawiki_88x31.png" );
                $text = '<a href="//www.mediawiki.org/"><img src="' . $url
                        . '" height="31" width="88" alt="Powered by MediaWiki" /></a>';
-               wfRunHooks( 'SkinGetPoweredBy', array( &$text, $this ) );
+               Hooks::run( 'SkinGetPoweredBy', array( &$text, $this ) );
                return $text;
        }
 
@@ -1224,7 +1224,7 @@ abstract class Skin extends ContextSource {
                if ( $wgEnableSidebarCache ) {
                        $cachedsidebar = $wgMemc->get( $key );
                        if ( $cachedsidebar ) {
-                               wfRunHooks( 'SidebarBeforeOutput', array( $this, &$cachedsidebar ) );
+                               Hooks::run( 'SidebarBeforeOutput', array( $this, &$cachedsidebar ) );
 
                                wfProfileOut( __METHOD__ );
                                return $cachedsidebar;
@@ -1234,12 +1234,12 @@ abstract class Skin extends ContextSource {
                $bar = array();
                $this->addToSidebar( $bar, 'sidebar' );
 
-               wfRunHooks( 'SkinBuildSidebar', array( $this, &$bar ) );
+               Hooks::run( 'SkinBuildSidebar', array( $this, &$bar ) );
                if ( $wgEnableSidebarCache ) {
                        $wgMemc->set( $key, $bar, $wgSidebarCacheExpiry );
                }
 
-               wfRunHooks( 'SidebarBeforeOutput', array( $this, &$bar ) );
+               Hooks::run( 'SidebarBeforeOutput', array( $this, &$bar ) );
 
                wfProfileOut( __METHOD__ );
                return $bar;
@@ -1379,7 +1379,7 @@ abstract class Skin extends ContextSource {
                $out = $this->getOutput();
 
                // Allow extensions to disable or modify the new messages alert
-               if ( !wfRunHooks( 'GetNewMessagesAlert', array( &$newMessagesAlert, $newtalks, $user, $out ) ) ) {
+               if ( !Hooks::run( 'GetNewMessagesAlert', array( &$newMessagesAlert, $newtalks, $user, $out ) ) ) {
                        return '';
                }
                if ( $newMessagesAlert ) {
@@ -1542,7 +1542,7 @@ abstract class Skin extends ContextSource {
                wfProfileIn( __METHOD__ );
                $siteNotice = '';
 
-               if ( wfRunHooks( 'SiteNoticeBefore', array( &$siteNotice, $this ) ) ) {
+               if ( Hooks::run( 'SiteNoticeBefore', array( &$siteNotice, $this ) ) ) {
                        if ( is_object( $this->getUser() ) && $this->getUser()->isLoggedIn() ) {
                                $siteNotice = $this->getCachedNotice( 'sitenotice' );
                        } else {
@@ -1558,7 +1558,7 @@ abstract class Skin extends ContextSource {
                        }
                }
 
-               wfRunHooks( 'SiteNoticeAfter', array( &$siteNotice, $this ) );
+               Hooks::run( 'SiteNoticeAfter', array( &$siteNotice, $this ) );
                wfProfileOut( __METHOD__ );
                return $siteNotice;
        }
@@ -1602,7 +1602,7 @@ abstract class Skin extends ContextSource {
                        . '<span class="mw-editsection-bracket">]</span>'
                        . '</span>';
 
-               wfRunHooks( 'DoEditSectionLink', array( $this, $nt, $section, $tooltip, &$result, $lang ) );
+               Hooks::run( 'DoEditSectionLink', array( $this, $nt, $section, $tooltip, &$result, $lang ) );
                return $result;
        }
 
index 3a39fee..d393280 100644 (file)
@@ -163,7 +163,7 @@ class SkinTemplate extends Skin {
                                        'lang' => $ilInterwikiCodeBCP47,
                                        'hreflang' => $ilInterwikiCodeBCP47,
                                );
-                               wfRunHooks(
+                               Hooks::run(
                                        'SkinTemplateGetLanguageLink',
                                        array( &$languageLink, $languageLinkTitle, $this->getTitle(), $this->getOutput() )
                                );
@@ -484,7 +484,7 @@ class SkinTemplate extends Skin {
                $tpl->set( 'reporttime', wfReportTime() );
 
                // original version by hansm
-               if ( !wfRunHooks( 'SkinTemplateOutputPageBeforeExec', array( &$this, &$tpl ) ) ) {
+               if ( !Hooks::run( 'SkinTemplateOutputPageBeforeExec', array( &$this, &$tpl ) ) ) {
                        wfDebug( __METHOD__ . ": Hook SkinTemplateOutputPageBeforeExec broke outputPage execution!\n" );
                }
 
@@ -703,7 +703,7 @@ class SkinTemplate extends Skin {
                        $personal_urls['login'] = $login_url;
                }
 
-               wfRunHooks( 'PersonalUrls', array( &$personal_urls, &$title, $this ) );
+               Hooks::run( 'PersonalUrls', array( &$personal_urls, &$title, $this ) );
                wfProfileOut( __METHOD__ );
                return $personal_urls;
        }
@@ -749,7 +749,7 @@ class SkinTemplate extends Skin {
                }
 
                $result = array();
-               if ( !wfRunHooks( 'SkinTemplateTabAction', array( &$this,
+               if ( !Hooks::run( 'SkinTemplateTabAction', array( &$this,
                                $title, $message, $selected, $checkEdit,
                                &$classes, &$query, &$text, &$result ) ) ) {
                        return $result;
@@ -845,7 +845,7 @@ class SkinTemplate extends Skin {
                $userCanRead = $title->quickUserCan( 'read', $user );
 
                $preventActiveTabs = false;
-               wfRunHooks( 'SkinTemplatePreventOtherActiveTabs', array( &$this, &$preventActiveTabs ) );
+               Hooks::run( 'SkinTemplatePreventOtherActiveTabs', array( &$this, &$preventActiveTabs ) );
 
                // Checks if page is some kind of content
                if ( $title->canExist() ) {
@@ -1054,7 +1054,7 @@ class SkinTemplate extends Skin {
                                }
                        }
 
-                       wfRunHooks( 'SkinTemplateNavigation', array( &$this, &$content_navigation ) );
+                       Hooks::run( 'SkinTemplateNavigation', array( &$this, &$content_navigation ) );
 
                        if ( $userCanRead && !$wgDisableLangConversion ) {
                                $pageLang = $title->getPageLanguage();
@@ -1096,12 +1096,12 @@ class SkinTemplate extends Skin {
                                'context' => 'subject'
                        );
 
-                       wfRunHooks( 'SkinTemplateNavigation::SpecialPage',
+                       Hooks::run( 'SkinTemplateNavigation::SpecialPage',
                                array( &$this, &$content_navigation ) );
                }
 
                // Equiv to SkinTemplateContentActions
-               wfRunHooks( 'SkinTemplateNavigation::Universal', array( &$this, &$content_navigation ) );
+               Hooks::run( 'SkinTemplateNavigation::Universal', array( &$this, &$content_navigation ) );
 
                // Setup xml ids and tooltip info
                foreach ( $content_navigation as $section => &$links ) {
@@ -1243,7 +1243,7 @@ class SkinTemplate extends Skin {
                        }
 
                        // Use the copy of revision ID in case this undocumented, shady hook tries to mess with internals
-                       wfRunHooks( 'SkinTemplateBuildNavUrlsNav_urlsAfterPermalink',
+                       Hooks::run( 'SkinTemplateBuildNavUrlsNav_urlsAfterPermalink',
                                array( &$this, &$nav_urls, &$revid, &$revid ) );
                }
 
index c28aa86..3476c26 100644 (file)
@@ -154,7 +154,7 @@ abstract class ChangesListSpecialPage extends SpecialPage {
        protected function getCustomFilters() {
                if ( $this->customFilters === null ) {
                        $this->customFilters = array();
-                       wfRunHooks( 'ChangesListSpecialPageFilters', array( $this, &$this->customFilters ) );
+                       Hooks::run( 'ChangesListSpecialPageFilters', array( $this, &$this->customFilters ) );
                }
 
                return $this->customFilters;
@@ -310,16 +310,16 @@ abstract class ChangesListSpecialPage extends SpecialPage {
        }
 
        protected function runMainQueryHook( &$tables, &$fields, &$conds, &$query_options, &$join_conds, $opts ) {
-               return wfRunHooks(
+               return Hooks::run(
                        'ChangesListSpecialPageQuery',
                        array( $this->getName(), &$tables, &$fields, &$conds, &$query_options, &$join_conds, $opts )
                );
        }
 
        /**
-        * Return a DatabaseBase object for reading
+        * Return a IDatabase object for reading
         *
-        * @return DatabaseBase
+        * @return IDatabase
         */
        protected function getDB() {
                return wfGetDB( DB_SLAVE );
index bf86ab2..fd3bc7b 100644 (file)
@@ -106,7 +106,7 @@ abstract class FormSpecialPage extends SpecialPage {
                $this->alterForm( $form );
 
                // Give hooks a chance to alter the form, adding extra fields or text etc
-               wfRunHooks( 'SpecialPageBeforeFormDisplay', array( $this->getName(), &$form ) );
+               Hooks::run( 'SpecialPageBeforeFormDisplay', array( $this->getName(), &$form ) );
 
                return $form;
        }
index c837d1a..c4e53ee 100644 (file)
@@ -35,7 +35,7 @@ abstract class ImageQueryPage extends QueryPage {
         *
         * @param OutputPage $out OutputPage to print to
         * @param Skin $skin User skin to use [unused]
-        * @param DatabaseBase $dbr (read) connection to use
+        * @param IDatabase $dbr (read) connection to use
         * @param ResultWrapper $res Result pointer
         * @param int $num Number of available result rows
         * @param int $offset Paging offset
index afc0227..d72744b 100644 (file)
@@ -32,7 +32,7 @@ abstract class PageQueryPage extends QueryPage {
         * like page existence and information for stub color and redirect hints.
         * This should be done for live data and cached data.
         *
-        * @param DatabaseBase $db
+        * @param IDatabase $db
         * @param ResultWrapper $res
         */
        public function preprocessResults( $db, $res ) {
index 167135b..dd21af4 100644 (file)
@@ -100,7 +100,7 @@ abstract class QueryPage extends SpecialPage {
                                array( 'UnusedtemplatesPage', 'Unusedtemplates' ),
                                array( 'WithoutInterwikiPage', 'Withoutinterwiki' ),
                        );
-                       wfRunHooks( 'wgQueryPages', array( &$qp ) );
+                       Hooks::run( 'wgQueryPages', array( &$qp ) );
                }
 
                return $qp;
@@ -346,7 +346,7 @@ abstract class QueryPage extends SpecialPage {
 
        /**
         * Get a DB connection to be used for slow recache queries
-        * @return DatabaseBase
+        * @return IDatabase
         */
        function getRecacheDB() {
                return wfGetDB( DB_SLAVE, array( $this->getName(), 'QueryPage::recache', 'vslow' ) );
@@ -576,7 +576,7 @@ abstract class QueryPage extends SpecialPage {
         *
         * @param OutputPage $out OutputPage to print to
         * @param Skin $skin User skin to use
-        * @param DatabaseBase $dbr Database (read) connection to use
+        * @param IDatabase $dbr Database (read) connection to use
         * @param ResultWrapper $res Result pointer
         * @param int $num Number of available result rows
         * @param int $offset Paging offset
@@ -649,7 +649,7 @@ abstract class QueryPage extends SpecialPage {
 
        /**
         * Do any necessary preprocessing of the result object.
-        * @param DatabaseBase $db
+        * @param IDatabase $db
         * @param ResultWrapper $res
         */
        function preprocessResults( $db, $res ) {
index 4226ee0..2e6e55a 100644 (file)
@@ -203,7 +203,7 @@ abstract class RedirectSpecialArticle extends RedirectSpecialPage {
                        'ctype', 'maxage', 'smaxage',
                );
 
-               wfRunHooks( "RedirectSpecialArticleRedirectParams", array( &$redirectParams ) );
+               Hooks::run( "RedirectSpecialArticleRedirectParams", array( &$redirectParams ) );
                $this->mAllowedRedirectParams = $redirectParams;
        }
 }
index 072f87f..759d7cb 100644 (file)
@@ -377,7 +377,7 @@ class SpecialPage {
                 * @param SpecialPage $this
                 * @param string|null $subPage
                 */
-               wfRunHooks( 'SpecialPageBeforeExecute', array( $this, $subPage ) );
+               Hooks::run( 'SpecialPageBeforeExecute', array( $this, $subPage ) );
 
                $this->beforeExecute( $subPage );
                $this->execute( $subPage );
@@ -391,7 +391,7 @@ class SpecialPage {
                 * @param SpecialPage $this
                 * @param string|null $subPage
                 */
-               wfRunHooks( 'SpecialPageAfterExecute', array( $this, $subPage ) );
+               Hooks::run( 'SpecialPageAfterExecute', array( $this, $subPage ) );
        }
 
        /**
index 1531f69..e31ebf6 100644 (file)
@@ -252,7 +252,7 @@ class SpecialPageFactory {
 
                        // Run hooks
                        // This hook can be used to remove undesired built-in special pages
-                       wfRunHooks( 'SpecialPage_initList', array( &self::$list ) );
+                       Hooks::run( 'SpecialPage_initList', array( &self::$list ) );
 
                        wfProfileOut( __METHOD__ );
                }
index be2f1e8..c4140de 100644 (file)
@@ -37,7 +37,7 @@ abstract class WantedQueryPage extends QueryPage {
 
        /**
         * Cache page existence for performance
-        * @param DatabaseBase $db
+        * @param IDatabase $db
         * @param ResultWrapper $res
         */
        function preprocessResults( $db, $res ) {
@@ -109,7 +109,7 @@ abstract class WantedQueryPage extends QueryPage {
         * @note This will only be run if the page is cached (ie $wgMiserMode = true)
         *   unless forceExistenceCheck() is true.
         * @since 1.24
-        * @return boolean
+        * @return bool
         */
        protected function existenceCheck( Title $title ) {
                return $title->isKnown();
index a4269d1..144d39b 100644 (file)
@@ -220,7 +220,7 @@ class SpecialBlock extends FormSpecialPage {
                $this->maybeAlterFormDefaults( $a );
 
                // Allow extensions to add more fields
-               wfRunHooks( 'SpecialBlockModifyFormFields', array( $this, &$a ) );
+               Hooks::run( 'SpecialBlockModifyFormFields', array( $this, &$a ) );
 
                return $a;
        }
@@ -317,7 +317,7 @@ class SpecialBlock extends FormSpecialPage {
                $otherBlockMessages = array();
                if ( $this->target !== null ) {
                        # Get other blocks, i.e. from GlobalBlocking or TorBlock extension
-                       wfRunHooks( 'OtherBlockLogLink', array( &$otherBlockMessages, $this->target ) );
+                       Hooks::run( 'OtherBlockLogLink', array( &$otherBlockMessages, $this->target ) );
 
                        if ( count( $otherBlockMessages ) ) {
                                $s = Html::rawElement(
@@ -701,7 +701,7 @@ class SpecialBlock extends FormSpecialPage {
                $block->mHideName = $data['HideUser'];
 
                $reason = array( 'hookaborted' );
-               if ( !wfRunHooks( 'BlockIp', array( &$block, &$performer, &$reason ) ) ) {
+               if ( !Hooks::run( 'BlockIp', array( &$block, &$performer, &$reason ) ) ) {
                        return $reason;
                }
 
@@ -762,7 +762,7 @@ class SpecialBlock extends FormSpecialPage {
                        $logaction = 'block';
                }
 
-               wfRunHooks( 'BlockIpComplete', array( $block, $performer ) );
+               Hooks::run( 'BlockIpComplete', array( $block, $performer ) );
 
                # Set *_deleted fields if requested
                if ( $data['HideUser'] ) {
index 02b2626..da6f4c0 100644 (file)
@@ -170,7 +170,7 @@ class SpecialBlockList extends SpecialPage {
 
                # Check for other blocks, i.e. global/tor blocks
                $otherBlockLink = array();
-               wfRunHooks( 'OtherBlockLogLink', array( &$otherBlockLink, $this->target ) );
+               Hooks::run( 'OtherBlockLogLink', array( &$otherBlockLink, $this->target ) );
 
                $out = $this->getOutput();
 
index d8eec7d..91a148d 100644 (file)
@@ -161,7 +161,7 @@ class SpecialBookSources extends SpecialPage {
 
                # Hook to allow extensions to insert additional HTML,
                # e.g. for API-interacting plugins and so on
-               wfRunHooks( 'BookInformation', array( $this->isbn, $this->getOutput() ) );
+               Hooks::run( 'BookInformation', array( $this->isbn, $this->getOutput() ) );
 
                # Check for a local page such as Project:Book_sources and use that if available
                $page = $this->msg( 'booksources' )->inContentLanguage()->text();
index 12bbd2a..e09c8ac 100644 (file)
@@ -183,7 +183,7 @@ class SpecialChangeEmail extends FormSpecialPage {
                        return $status;
                }
 
-               wfRunHooks( 'PrefsEmailAudit', array( $user, $oldaddr, $newaddr ) );
+               Hooks::run( 'PrefsEmailAudit', array( $user, $oldaddr, $newaddr ) );
 
                $user->saveSettings();
 
index 24664ed..168095f 100644 (file)
@@ -118,7 +118,7 @@ class SpecialChangePassword extends FormSpecialPage {
                }
 
                $extraFields = array();
-               wfRunHooks( 'ChangePasswordForm', array( &$extraFields ) );
+               Hooks::run( 'ChangePasswordForm', array( &$extraFields ) );
                foreach ( $extraFields as $extra ) {
                        list( $name, $label, $type, $default ) = $extra;
                        $fields[$name] = array(
@@ -248,7 +248,7 @@ class SpecialChangePassword extends FormSpecialPage {
                }
 
                if ( $newpass !== $retype ) {
-                       wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'badretype' ) );
+                       Hooks::run( 'PrefsPasswordAudit', array( $user, $newpass, 'badretype' ) );
                        throw new PasswordError( $this->msg( 'badretype' )->text() );
                }
 
@@ -264,7 +264,7 @@ class SpecialChangePassword extends FormSpecialPage {
 
                // @todo Make these separate messages, since the message is written for both cases
                if ( !$user->checkTemporaryPassword( $oldpass ) && !$user->checkPassword( $oldpass ) ) {
-                       wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'wrongpassword' ) );
+                       Hooks::run( 'PrefsPasswordAudit', array( $user, $newpass, 'wrongpassword' ) );
                        throw new PasswordError( $this->msg( 'resetpass-wrong-oldpass' )->text() );
                }
 
@@ -276,8 +276,8 @@ class SpecialChangePassword extends FormSpecialPage {
                // Do AbortChangePassword after checking mOldpass, so we don't leak information
                // by possibly aborting a new password before verifying the old password.
                $abortMsg = 'resetpass-abort-generic';
-               if ( !wfRunHooks( 'AbortChangePassword', array( $user, $oldpass, $newpass, &$abortMsg ) ) ) {
-                       wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'abortreset' ) );
+               if ( !Hooks::run( 'AbortChangePassword', array( $user, $oldpass, $newpass, &$abortMsg ) ) ) {
+                       Hooks::run( 'PrefsPasswordAudit', array( $user, $newpass, 'abortreset' ) );
                        throw new PasswordError( $this->msg( $abortMsg )->text() );
                }
 
@@ -288,9 +288,9 @@ class SpecialChangePassword extends FormSpecialPage {
 
                try {
                        $user->setPassword( $newpass );
-                       wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'success' ) );
+                       Hooks::run( 'PrefsPasswordAudit', array( $user, $newpass, 'success' ) );
                } catch ( PasswordError $e ) {
-                       wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'error' ) );
+                       Hooks::run( 'PrefsPasswordAudit', array( $user, $newpass, 'error' ) );
                        throw new PasswordError( $e->getMessage() );
                }
 
index 1e829b1..7cc5425 100644 (file)
@@ -176,7 +176,7 @@ class SpecialContributions extends IncludableSpecialPage {
                // Add RSS/atom links
                $this->addFeedLinks( $feedParams );
 
-               if ( wfRunHooks( 'SpecialContributionsBeforeMainOutput', array( $id, $userObj, $this ) ) ) {
+               if ( Hooks::run( 'SpecialContributionsBeforeMainOutput', array( $id, $userObj, $this ) ) ) {
                        if ( !$this->including() ) {
                                $out->addHTML( $this->getForm() );
                        }
@@ -386,7 +386,7 @@ class SpecialContributions extends IncludableSpecialPage {
                        );
                }
 
-               wfRunHooks( 'ContributionsToolLinks', array( $id, $userpage, &$tools ) );
+               Hooks::run( 'ContributionsToolLinks', array( $id, $userpage, &$tools ) );
 
                return $tools;
        }
@@ -672,10 +672,7 @@ class ContribsPager extends ReverseChronologicalPager {
                $msgs = array(
                        'diff',
                        'hist',
-                       'newarticle',
                        'pipe-separator',
-                       'rev-delundel',
-                       'rollbacklink',
                        'uctop'
                );
 
@@ -750,7 +747,7 @@ class ContribsPager extends ReverseChronologicalPager {
                $data = array( $this->mDb->select(
                        $tables, $fields, $conds, $fname, $options, $join_conds
                ) );
-               wfRunHooks(
+               Hooks::run(
                        'ContribsPager::reallyDoQuery',
                        array( &$data, $pager, $offset, $limit, $descending )
                );
@@ -827,7 +824,7 @@ class ContribsPager extends ReverseChronologicalPager {
                        $this->tagFilter
                );
 
-               wfRunHooks( 'ContribsPager::getQueryInfo', array( &$this, &$queryInfo ) );
+               Hooks::run( 'ContribsPager::getQueryInfo', array( &$this, &$queryInfo ) );
 
                return $queryInfo;
        }
@@ -1112,7 +1109,7 @@ class ContribsPager extends ReverseChronologicalPager {
                }
 
                // Let extensions add data
-               wfRunHooks( 'ContributionsLineEnding', array( $this, &$ret, $row, &$classes ) );
+               Hooks::run( 'ContributionsLineEnding', array( $this, &$ret, $row, &$classes ) );
 
                if ( $classes === array() && $ret === '' ) {
                        wfDebug( "Dropping Special:Contribution row that could not be formatted\n" );
index 29c3fd4..7e5d13c 100644 (file)
@@ -466,7 +466,7 @@ class DeletedContributionsPage extends SpecialPage {
                                );
                        }
 
-                       wfRunHooks( 'ContributionsToolLinks', array( $id, $nt, &$tools ) );
+                       Hooks::run( 'ContributionsToolLinks', array( $id, $nt, &$tools ) );
 
                        $links = $this->getLanguage()->pipeList( $tools );
 
index cb97420..e42db8c 100644 (file)
@@ -513,7 +513,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
                                );
 
                                $page = WikiPage::factory( $title );
-                               wfRunHooks( 'UnwatchArticleComplete', array( $this->getUser(), &$page ) );
+                               Hooks::run( 'UnwatchArticleComplete', array( $this->getUser(), &$page ) );
                        }
                }
        }
@@ -551,7 +551,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
                // Allow subscribers to manipulate the list of watched pages (or use it
                // to preload lots of details at once)
                $watchlistInfo = $this->getWatchlistInfo();
-               wfRunHooks(
+               Hooks::run(
                        'WatchlistEditorBeforeFormRender',
                        array( &$watchlistInfo )
                );
@@ -645,7 +645,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
                        );
                }
 
-               wfRunHooks(
+               Hooks::run(
                        'WatchlistEditorBuildRemoveLine',
                        array( &$tools, $title, $title->isRedirect(), $this->getSkin(), &$link )
                );
index 20532a9..c55fa94 100644 (file)
@@ -160,7 +160,7 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                $form->setWrapperLegendMsg( 'email-legend' );
                $form->loadData();
 
-               if ( !wfRunHooks( 'EmailUserForm', array( &$form ) ) ) {
+               if ( !Hooks::run( 'EmailUserForm', array( &$form ) ) ) {
                        return;
                }
 
@@ -243,8 +243,8 @@ class SpecialEmailUser extends UnlistedSpecialPage {
 
                $hookErr = false;
 
-               wfRunHooks( 'UserCanSendEmail', array( &$user, &$hookErr ) );
-               wfRunHooks( 'EmailUserPermissionsErrors', array( $user, $editToken, &$hookErr ) );
+               Hooks::run( 'UserCanSendEmail', array( &$user, &$hookErr ) );
+               Hooks::run( 'EmailUserPermissionsErrors', array( $user, $editToken, &$hookErr ) );
 
                if ( $hookErr ) {
                        return $hookErr;
@@ -324,7 +324,7 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                        $from->name, $to->name )->inContentLanguage()->text();
 
                $error = '';
-               if ( !wfRunHooks( 'EmailUser', array( &$to, &$from, &$subject, &$text, &$error ) ) ) {
+               if ( !Hooks::run( 'EmailUser', array( &$to, &$from, &$subject, &$text, &$error ) ) ) {
                        return $error;
                }
 
@@ -367,12 +367,12 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                        if ( $data['CCMe'] && $to != $from ) {
                                $cc_subject = $context->msg( 'emailccsubject' )->rawParams(
                                        $target->getName(), $subject )->text();
-                               wfRunHooks( 'EmailUserCC', array( &$from, &$from, &$cc_subject, &$text ) );
+                               Hooks::run( 'EmailUserCC', array( &$from, &$from, &$cc_subject, &$text ) );
                                $ccStatus = UserMailer::send( $from, $from, $cc_subject, $text );
                                $status->merge( $ccStatus );
                        }
 
-                       wfRunHooks( 'EmailUserComplete', array( $to, $from, $subject, $text ) );
+                       Hooks::run( 'EmailUserComplete', array( $to, $from, $subject, $text ) );
 
                        return $status;
                }
index 0831c20..da2df2d 100644 (file)
@@ -579,7 +579,7 @@ class ImportReporter extends ContextSource {
                                $page = WikiPage::factory( $title );
                                # Update page record
                                $page->updateRevisionOn( $dbw, $nullRevision );
-                               wfRunHooks(
+                               Hooks::run(
                                        'NewRevisionFromEditComplete',
                                        array( $page, $nullRevision, $latest, $this->getUser() )
                                );
index fa20994..68c5346 100644 (file)
@@ -150,7 +150,7 @@ class UsersPager extends AlphabeticPager {
                        'conds' => $conds
                );
 
-               wfRunHooks( 'SpecialListusersQueryInfo', array( $this, &$query ) );
+               Hooks::run( 'SpecialListusersQueryInfo', array( $this, &$query ) );
 
                return $query;
        }
@@ -211,7 +211,7 @@ class UsersPager extends AlphabeticPager {
                        ' ' . $this->msg( 'listusers-blocked', $userName )->escaped() :
                        '';
 
-               wfRunHooks( 'SpecialListusersFormatRow', array( &$item, $row ) );
+               Hooks::run( 'SpecialListusersFormatRow', array( &$item, $row ) );
 
                return Html::rawElement( 'li', array(), "{$item}{$edits}{$created}{$blocked}" );
        }
@@ -284,12 +284,12 @@ class UsersPager extends AlphabeticPager {
                );
                $out .= '<br />';
 
-               wfRunHooks( 'SpecialListusersHeaderForm', array( $this, &$out ) );
+               Hooks::run( 'SpecialListusersHeaderForm', array( $this, &$out ) );
 
                # Submit button and form bottom
                $out .= Html::hidden( 'limit', $this->mLimit );
                $out .= Xml::submitButton( $this->msg( 'allpagessubmit' )->text() );
-               wfRunHooks( 'SpecialListusersHeader', array( $this, &$out ) );
+               Hooks::run( 'SpecialListusersHeader', array( $this, &$out ) );
                $out .= Xml::closeElement( 'fieldset' ) .
                        Xml::closeElement( 'form' );
 
@@ -322,7 +322,7 @@ class UsersPager extends AlphabeticPager {
                if ( $this->requestedUser != '' ) {
                        $query['username'] = $this->requestedUser;
                }
-               wfRunHooks( 'SpecialListusersDefaultQuery', array( $this, &$query ) );
+               Hooks::run( 'SpecialListusersDefaultQuery', array( $this, &$query ) );
 
                return $query;
        }
index 04c2fe9..923283e 100644 (file)
@@ -97,13 +97,13 @@ class SpecialLog extends SpecialPage {
                        }
                } else {
                        // Allow extensions to add relations to their search types
-                       wfRunHooks( 'SpecialLogAddLogSearchRelations', array( $opts->getValue( 'type' ), $this->getRequest(), &$qc ) );
+                       Hooks::run( 'SpecialLogAddLogSearchRelations', array( $opts->getValue( 'type' ), $this->getRequest(), &$qc ) );
                }
 
                # Some log types are only for a 'User:' title but we might have been given
                # only the username instead of the full title 'User:username'. This part try
                # to lookup for a user by that name and eventually fix user input. See bug 1697.
-               wfRunHooks( 'GetLogTypesOnUser', array( &$this->typeOnUser ) );
+               Hooks::run( 'GetLogTypesOnUser', array( &$this->typeOnUser ) );
                if ( in_array( $opts->getValue( 'type' ), $this->typeOnUser ) ) {
                        # ok we have a type of log which expect a user title.
                        $target = Title::newFromText( $opts->getValue( 'page' ) );
index f533234..c072491 100644 (file)
@@ -72,7 +72,7 @@ class LonelyPagesPage extends PageQueryPage {
                );
 
                // Allow extensions to modify the query
-               wfRunHooks( 'LonelyPagesQuery', array( &$tables, &$conds, &$joinConds ) );
+               Hooks::run( 'LonelyPagesQuery', array( &$tables, &$conds, &$joinConds ) );
 
                return array(
                        'tables' => $tables,
index c71ef76..07a18b0 100644 (file)
@@ -485,7 +485,7 @@ class SpecialMergeHistory extends SpecialPage {
                        $targetTitle->getPrefixedText(), $destTitle->getPrefixedText() )->numParams(
                        $count )->text() );
 
-               wfRunHooks( 'ArticleMergeComplete', array( $targetTitle, $destTitle ) );
+               Hooks::run( 'ArticleMergeComplete', array( $targetTitle, $destTitle ) );
 
                return true;
        }
index 4cbf584..2a7e435 100644 (file)
@@ -604,7 +604,7 @@ class MovePageForm extends UnlistedSpecialPage {
                        $newLink )->params( $oldText, $newText )->parseAsBlock() );
                $out->addWikiMsg( $msgName );
 
-               wfRunHooks( 'SpecialMovepageAfterMove', array( &$this, &$ot, &$nt ) );
+               Hooks::run( 'SpecialMovepageAfterMove', array( &$this, &$ot, &$nt ) );
 
                # Now we move extra pages we've been asked to move: subpages and talk
                # pages.  First, if the old page or the new page is a talk page, we
index b3b3d48..aa16dbc 100644 (file)
@@ -56,7 +56,7 @@ class SpecialNewpages extends IncludableSpecialPage {
                $opts->add( 'invert', false );
 
                $this->customFilters = array();
-               wfRunHooks( 'SpecialNewPagesFilters', array( $this, &$this->customFilters ) );
+               Hooks::run( 'SpecialNewPagesFilters', array( $this, &$this->customFilters ) );
                foreach ( $this->customFilters as $key => $params ) {
                        $opts->add( $key, $params['default'] );
                }
@@ -548,7 +548,7 @@ class NewPagesPager extends ReverseChronologicalPager {
                );
                $join_conds = array( 'page' => array( 'INNER JOIN', 'page_id=rc_cur_id' ) );
 
-               wfRunHooks( 'SpecialNewpagesConditions',
+               Hooks::run( 'SpecialNewpagesConditions',
                        array( &$this, $this->opts, &$conds, &$tables, &$fields, &$join_conds ) );
 
                $options = array();
index 2acf23c..52c2460 100644 (file)
@@ -93,7 +93,7 @@ class SpecialPageLanguage extends FormSpecialPage {
        public function alterForm( HTMLForm $form ) {
                $form->setDisplayFormat( 'vform' );
                $form->setWrapperLegend( false );
-               wfRunHooks( 'LanguageSelector', array( $this->getOutput(), 'mw-languageselector' ) );
+               Hooks::run( 'LanguageSelector', array( $this->getOutput(), 'mw-languageselector' ) );
        }
 
        /**
index 3061c85..6ee3290 100644 (file)
@@ -195,7 +195,7 @@ class SpecialPasswordReset extends FormSpecialPage {
 
                // Check for hooks (captcha etc), and allow them to modify the users list
                $error = array();
-               if ( !wfRunHooks( 'SpecialPasswordResetOnSubmit', array( &$users, $data, &$error ) ) ) {
+               if ( !Hooks::run( 'SpecialPasswordResetOnSubmit', array( &$users, $data, &$error ) ) ) {
                        return array( $error );
                }
 
@@ -246,7 +246,7 @@ class SpecialPasswordReset extends FormSpecialPage {
                        return array( 'badipaddress' );
                }
                $caller = $this->getUser();
-               wfRunHooks( 'User::mailPasswordInternal', array( &$caller, &$ip, &$firstUser ) );
+               Hooks::run( 'User::mailPasswordInternal', array( &$caller, &$ip, &$firstUser ) );
                $username = $caller->getName();
                $msg = IP::isValid( $username )
                        ? 'passwordreset-emailtext-ip'
index 6d8f59b..73a88b9 100644 (file)
@@ -106,7 +106,7 @@ class RandomPage extends SpecialPage {
                $randstr = wfRandom();
                $title = null;
 
-               if ( !wfRunHooks(
+               if ( !Hooks::run(
                        'SpecialRandomGetRandomTitle',
                        array( &$randstr, &$this->isRedir, &$this->namespaces, &$this->extra, &$title )
                ) ) {
index 58b51b3..efb870b 100644 (file)
@@ -95,7 +95,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
        protected function getCustomFilters() {
                if ( $this->customFilters === null ) {
                        $this->customFilters = parent::getCustomFilters();
-                       wfRunHooks( 'SpecialRecentChangesFilters', array( $this, &$this->customFilters ), '1.23' );
+                       Hooks::run( 'SpecialRecentChangesFilters', array( $this, &$this->customFilters ), '1.23' );
                }
 
                return $this->customFilters;
@@ -254,7 +254,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
 
        protected function runMainQueryHook( &$tables, &$fields, &$conds, &$query_options, &$join_conds, $opts ) {
                return parent::runMainQueryHook( $tables, $fields, $conds, $query_options, $join_conds, $opts )
-                       && wfRunHooks(
+                       && Hooks::run(
                                'SpecialRecentChangesQuery',
                                array( &$conds, &$tables, &$join_conds, $opts, &$query_options, &$fields ),
                                '1.23'
@@ -475,7 +475,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
 
                // Don't fire the hook for subclasses. (Or should we?)
                if ( $this->getName() === 'Recentchanges' ) {
-                       wfRunHooks( 'SpecialRecentChangesPanel', array( &$extraOpts, $opts ) );
+                       Hooks::run( 'SpecialRecentChangesPanel', array( &$extraOpts, $opts ) );
                }
 
                return $extraOpts;
index 4add742..ba2b9a5 100644 (file)
@@ -44,7 +44,7 @@ class SpecialResetTokens extends FormSpecialPage {
                        $tokens = array(
                                array( 'preference' => 'watchlisttoken', 'label-message' => 'resettokens-watchlist-token' ),
                        );
-                       wfRunHooks( 'SpecialResetTokensTokens', array( &$tokens ) );
+                       Hooks::run( 'SpecialResetTokensTokens', array( &$tokens ) );
 
                        $hiddenPrefs = $this->getConfig()->get( 'HiddenPrefs' );
                        $tokens = array_filter( $tokens, function ( $tok ) use ( $hiddenPrefs ) {
index 448b802..1923d44 100644 (file)
@@ -196,7 +196,7 @@ class SpecialSearch extends SpecialPage {
                # No match, generate an edit URL
                $title = Title::newFromText( $term );
                if ( !is_null( $title ) ) {
-                       wfRunHooks( 'SpecialSearchNogomatch', array( &$title ) );
+                       Hooks::run( 'SpecialSearchNogomatch', array( &$title ) );
                }
                $this->showResults( $term );
        }
@@ -214,7 +214,7 @@ class SpecialSearch extends SpecialPage {
                $search->prefix = $this->mPrefix;
                $term = $search->transformSearchTerm( $term );
 
-               wfRunHooks( 'SpecialSearchSetupEngine', array( $this, $this->profile, $search ) );
+               Hooks::run( 'SpecialSearchSetupEngine', array( $this, $this->profile, $search ) );
 
                $this->setupPage( $term );
 
@@ -293,7 +293,7 @@ class SpecialSearch extends SpecialPage {
                                . $this->msg( 'search-suggest' )->rawParams( $suggestLink )->text() . '</div>';
                }
 
-               if ( !wfRunHooks( 'SpecialSearchResultsPrepend', array( $this, $out, $term ) ) ) {
+               if ( !Hooks::run( 'SpecialSearchResultsPrepend', array( $this, $out, $term ) ) ) {
                        # Hook requested termination
                        return;
                }
@@ -361,7 +361,7 @@ class SpecialSearch extends SpecialPage {
                                );
                        }
                }
-               wfRunHooks( 'SpecialSearchResults', array( $term, &$titleMatches, &$textMatches ) );
+               Hooks::run( 'SpecialSearchResults', array( $term, &$titleMatches, &$textMatches ) );
 
                $out->parserOptions()->setEditSection( false );
                if ( $titleMatches ) {
@@ -444,7 +444,7 @@ class SpecialSearch extends SpecialPage {
                        wfEscapeWikiText( $title->getPrefixedText() ),
                        Message::numParam( $num )
                );
-               wfRunHooks( 'SpecialSearchCreateLink', array( $title, &$params ) );
+               Hooks::run( 'SpecialSearchCreateLink', array( $title, &$params ) );
 
                // Extensions using the hook might still return an empty $messageName
                if ( $messageName ) {
@@ -595,7 +595,7 @@ class SpecialSearch extends SpecialPage {
 
                $link_t = clone $title;
 
-               wfRunHooks( 'ShowSearchHitTitle',
+               Hooks::run( 'ShowSearchHitTitle',
                        array( &$link_t, &$titleSnippet, $result, $terms, $this ) );
 
                $link = Linker::linkKnown(
@@ -713,7 +713,7 @@ class SpecialSearch extends SpecialPage {
                $html = null;
 
                $score = '';
-               if ( wfRunHooks( 'ShowSearchHit', array(
+               if ( Hooks::run( 'ShowSearchHit', array(
                        $this, $result, $terms,
                        &$link, &$redirect, &$section, &$extract,
                        &$score, &$size, &$date, &$related,
@@ -907,7 +907,7 @@ class SpecialSearch extends SpecialPage {
 
                $showSections = array( 'namespaceTables' => $namespaceTables );
 
-               wfRunHooks( 'SpecialSearchPowerBox', array( &$showSections, $term, $opts ) );
+               Hooks::run( 'SpecialSearchPowerBox', array( &$showSections, $term, $opts ) );
 
                $hidden = '';
                foreach ( $opts as $key => $value ) {
@@ -978,7 +978,7 @@ class SpecialSearch extends SpecialPage {
                        )
                );
 
-               wfRunHooks( 'SpecialSearchProfiles', array( &$profiles ) );
+               Hooks::run( 'SpecialSearchProfiles', array( &$profiles ) );
 
                foreach ( $profiles as &$data ) {
                        if ( !is_array( $data['namespaces'] ) ) {
@@ -1044,7 +1044,7 @@ class SpecialSearch extends SpecialPage {
                        $out .= $this->powerSearchBox( $term, $opts );
                } else {
                        $form = '';
-                       wfRunHooks( 'SpecialSearchProfileForm', array( $this, &$form, $this->profile, $term, $opts ) );
+                       Hooks::run( 'SpecialSearchProfileForm', array( $this, &$form, $this->profile, $term, $opts ) );
                        $out .= $form;
                }
 
index 1bbc2f3..4429022 100644 (file)
@@ -78,7 +78,7 @@ class SpecialStatistics extends SpecialPage {
 
                # Statistic - other
                $extraStats = array();
-               if ( wfRunHooks( 'SpecialStatsAddExtra', array( &$extraStats ) ) ) {
+               if ( Hooks::run( 'SpecialStatsAddExtra', array( &$extraStats ) ) ) {
                        $text .= $this->getOtherStats( $extraStats );
                }
 
index bcf83c8..2ea1b12 100644 (file)
@@ -421,7 +421,7 @@ class PageArchive {
                $logEntry->setTarget( $this->title );
                $logEntry->setComment( $reason );
 
-               wfRunHooks( 'ArticleUndeleteLogEntry', array( $this, &$logEntry, $user ) );
+               Hooks::run( 'ArticleUndeleteLogEntry', array( $this, &$logEntry, $user ) );
 
                $logid = $logEntry->insert();
                $logEntry->publish( $logid );
@@ -605,7 +605,7 @@ class PageArchive {
                        $revision->insertOn( $dbw );
                        $restored++;
 
-                       wfRunHooks( 'ArticleRevisionUndeleted', array( &$this->title, $revision, $row->ar_page_id ) );
+                       Hooks::run( 'ArticleRevisionUndeleted', array( &$this->title, $revision, $row->ar_page_id ) );
                }
                # Now that it's safely stored, take it out of the archive
                $dbw->delete( 'archive',
@@ -631,7 +631,7 @@ class PageArchive {
                        );
                }
 
-               wfRunHooks( 'ArticleUndelete', array( &$this->title, $created, $comment, $oldPageId ) );
+               Hooks::run( 'ArticleUndelete', array( &$this->title, $created, $comment, $oldPageId ) );
 
                if ( $this->title->getNamespace() == NS_FILE ) {
                        $update = new HTMLCacheUpdate( $this->title, 'imagelinks' );
@@ -908,7 +908,7 @@ class SpecialUndelete extends SpecialPage {
                }
 
                $archive = new PageArchive( $this->mTargetObj, $this->getConfig() );
-               if ( !wfRunHooks( 'UndeleteForm::showRevision', array( &$archive, $this->mTargetObj ) ) ) {
+               if ( !Hooks::run( 'UndeleteForm::showRevision', array( &$archive, $this->mTargetObj ) ) ) {
                        return;
                }
                $rev = $archive->getRevision( $timestamp );
@@ -992,7 +992,7 @@ class SpecialUndelete extends SpecialPage {
                $out->addHTML( $this->msg( 'undelete-revision' )->rawParams( $link )->params(
                        $time )->rawParams( $userLink )->params( $d, $t )->parse() . '</div>' );
 
-               if ( !wfRunHooks( 'UndeleteShowRevision', array( $this->mTargetObj, $rev ) ) ) {
+               if ( !Hooks::run( 'UndeleteShowRevision', array( $this->mTargetObj, $rev ) ) ) {
                        return;
                }
 
@@ -1215,7 +1215,7 @@ class SpecialUndelete extends SpecialPage {
                );
 
                $archive = new PageArchive( $this->mTargetObj, $this->getConfig() );
-               wfRunHooks( 'UndeleteForm::showHistory', array( &$archive, $this->mTargetObj ) );
+               Hooks::run( 'UndeleteForm::showHistory', array( &$archive, $this->mTargetObj ) );
                /*
                $text = $archive->getLastRevisionText();
                if( is_null( $text ) ) {
@@ -1640,7 +1640,7 @@ class SpecialUndelete extends SpecialPage {
 
                $out = $this->getOutput();
                $archive = new PageArchive( $this->mTargetObj, $this->getConfig() );
-               wfRunHooks( 'UndeleteForm::undelete', array( &$archive, $this->mTargetObj ) );
+               Hooks::run( 'UndeleteForm::undelete', array( &$archive, $this->mTargetObj ) );
                $ok = $archive->undelete(
                        $this->mTargetTimestamp,
                        $this->mComment,
@@ -1651,7 +1651,7 @@ class SpecialUndelete extends SpecialPage {
 
                if ( is_array( $ok ) ) {
                        if ( $ok[1] ) { // Undeleted file count
-                               wfRunHooks( 'FileUndeleteComplete', array(
+                               Hooks::run( 'FileUndeleteComplete', array(
                                        $this->mTargetObj, $this->mFileVersions,
                                        $this->getUser(), $this->mComment ) );
                        }
index ccc5dea..ff0ccc1 100644 (file)
@@ -186,7 +186,7 @@ class SpecialUpload extends SpecialPage {
                        $this->processUpload();
                } else {
                        # Backwards compatibility hook
-                       if ( !wfRunHooks( 'UploadForm:initial', array( &$this ) ) ) {
+                       if ( !Hooks::run( 'UploadForm:initial', array( &$this ) ) ) {
                                wfDebug( "Hook 'UploadForm:initial' broke output of the upload form\n" );
 
                                return;
@@ -414,7 +414,7 @@ class SpecialUpload extends SpecialPage {
                        return;
                }
 
-               if ( !wfRunHooks( 'UploadForm:BeforeProcessing', array( &$this ) ) ) {
+               if ( !Hooks::run( 'UploadForm:BeforeProcessing', array( &$this ) ) ) {
                        wfDebug( "Hook 'UploadForm:BeforeProcessing' broke processing the file.\n" );
                        // This code path is deprecated. If you want to break upload processing
                        // do so by hooking into the appropriate hooks in UploadBase::verifyUpload
@@ -474,7 +474,7 @@ class SpecialUpload extends SpecialPage {
 
                // Success, redirect to description page
                $this->mUploadSuccessful = true;
-               wfRunHooks( 'SpecialUploadComplete', array( &$this ) );
+               Hooks::run( 'SpecialUploadComplete', array( &$this ) );
                $this->getOutput()->redirect( $this->mLocalFile->getTitle()->getFullURL() );
        }
 
@@ -795,7 +795,7 @@ class UploadForm extends HTMLForm {
                        + $this->getDescriptionSection()
                        + $this->getOptionsSection();
 
-               wfRunHooks( 'UploadFormInitDescriptor', array( &$descriptor ) );
+               Hooks::run( 'UploadFormInitDescriptor', array( &$descriptor ) );
                parent::__construct( $descriptor, $context, 'upload' );
 
                # Add a link to edit MediaWik:Licenses
@@ -907,7 +907,7 @@ class UploadForm extends HTMLForm {
                                'checked' => $selectedSourceType == 'url',
                        );
                }
-               wfRunHooks( 'UploadFormSourceDescriptors', array( &$descriptor, &$radio, $selectedSourceType ) );
+               Hooks::run( 'UploadFormSourceDescriptors', array( &$descriptor, &$radio, $selectedSourceType ) );
 
                $descriptor['Extensions'] = array(
                        'type' => 'info',
index 83b9089..b7c7868 100644 (file)
@@ -122,7 +122,7 @@ class LoginForm extends SpecialPage {
                static $messages = null;
                if ( !$messages ) {
                        $messages = self::$validErrorMessages;
-                       wfRunHooks( 'LoginFormValidErrorMessages', array( &$messages ) );
+                       Hooks::run( 'LoginFormValidErrorMessages', array( &$messages ) );
                }
 
                return $messages;
@@ -352,7 +352,7 @@ class LoginForm extends SpecialPage {
                $u->saveSettings();
                $result = $this->mailPasswordInternal( $u, false, 'createaccount-title', 'createaccount-text' );
 
-               wfRunHooks( 'AddNewAccount', array( $u, true ) );
+               Hooks::run( 'AddNewAccount', array( $u, true ) );
                $u->addNewUserLogEntry( 'byemail', $this->mReason );
 
                $out = $this->getOutput();
@@ -427,7 +427,7 @@ class LoginForm extends SpecialPage {
                        // which is needed or the personal links will be
                        // wrong.
                        $this->getContext()->setUser( $u );
-                       wfRunHooks( 'AddNewAccount', array( $u, false ) );
+                       Hooks::run( 'AddNewAccount', array( $u, false ) );
                        $u->addNewUserLogEntry( 'create' );
                        if ( $this->hasSessionCookie() ) {
                                $this->successfulCreation();
@@ -439,7 +439,7 @@ class LoginForm extends SpecialPage {
                        $out->setPageTitle( $this->msg( 'accountcreated' ) );
                        $out->addWikiMsg( 'accountcreatedtext', $u->getName() );
                        $out->addReturnTo( $this->getPageTitle() );
-                       wfRunHooks( 'AddNewAccount', array( $u, false ) );
+                       Hooks::run( 'AddNewAccount', array( $u, false ) );
                        $u->addNewUserLogEntry( 'create2', $this->mReason );
                }
 
@@ -573,7 +573,7 @@ class LoginForm extends SpecialPage {
 
                $abortError = '';
                $abortStatus = null;
-               if ( !wfRunHooks( 'AbortNewAccount', array( $u, &$abortError, &$abortStatus ) ) ) {
+               if ( !Hooks::run( 'AbortNewAccount', array( $u, &$abortError, &$abortStatus ) ) ) {
                        // Hook point to add extra creation throttles and blocks
                        wfDebug( "LoginForm::addNewAccountInternal: a hook blocked creation\n" );
                        if ( $abortStatus === null ) {
@@ -593,7 +593,7 @@ class LoginForm extends SpecialPage {
                }
 
                // Hook point to check for exempt from account creation throttle
-               if ( !wfRunHooks( 'ExemptFromAccountCreationThrottle', array( $ip ) ) ) {
+               if ( !Hooks::run( 'ExemptFromAccountCreationThrottle', array( $ip ) ) ) {
                        wfDebug( "LoginForm::exemptFromAccountCreationThrottle: a hook " .
                                "allowed account creation w/o throttle\n" );
                } else {
@@ -716,7 +716,7 @@ class LoginForm extends SpecialPage {
 
                // Give extensions a way to indicate the username has been updated,
                // rather than telling the user the account doesn't exist.
-               if ( !wfRunHooks( 'LoginUserMigrated', array( $u, &$msg ) ) ) {
+               if ( !Hooks::run( 'LoginUserMigrated', array( $u, &$msg ) ) ) {
                        $this->mAbortLoginErrorMsg = $msg;
                        return self::USER_MIGRATED;
                }
@@ -740,7 +740,7 @@ class LoginForm extends SpecialPage {
                // Give general extensions, such as a captcha, a chance to abort logins
                $abort = self::ABORTED;
                $msg = null;
-               if ( !wfRunHooks( 'AbortLogin', array( $u, $this->mPassword, &$abort, &$msg ) ) ) {
+               if ( !Hooks::run( 'AbortLogin', array( $u, $this->mPassword, &$abort, &$msg ) ) ) {
                        $this->mAbortLoginErrorMsg = $msg;
 
                        return $abort;
@@ -801,12 +801,12 @@ class LoginForm extends SpecialPage {
 
                        if ( $isAutoCreated ) {
                                // Must be run after $wgUser is set, for correct new user log
-                               wfRunHooks( 'AuthPluginAutoCreate', array( $u ) );
+                               Hooks::run( 'AuthPluginAutoCreate', array( $u ) );
                        }
 
                        $retval = self::SUCCESS;
                }
-               wfRunHooks( 'LoginAuthenticateAudit', array( $u, $this->mPassword, $retval ) );
+               Hooks::run( 'LoginAuthenticateAudit', array( $u, $this->mPassword, $retval ) );
 
                return $retval;
        }
@@ -887,7 +887,7 @@ class LoginForm extends SpecialPage {
                }
 
                $abortError = '';
-               if ( !wfRunHooks( 'AbortAutoAccount', array( $user, &$abortError ) ) ) {
+               if ( !Hooks::run( 'AbortAutoAccount', array( $user, &$abortError ) ) ) {
                        // Hook point to add extra creation throttles and blocks
                        wfDebug( "LoginForm::attemptAutoCreate: a hook blocked creation: $abortError\n" );
                        $this->mAbortLoginErrorMsg = $abortError;
@@ -1040,7 +1040,7 @@ class LoginForm extends SpecialPage {
         */
        protected function resetLoginForm( Message $msg ) {
                // Allow hooks to explain this password reset in more detail
-               wfRunHooks( 'LoginPasswordResetMessage', array( &$msg, $this->mUsername ) );
+               Hooks::run( 'LoginPasswordResetMessage', array( &$msg, $this->mUsername ) );
                $reset = new SpecialChangePassword();
                $derivative = new DerivativeContext( $this->getContext() );
                $derivative->setTitle( $reset->getPageTitle() );
@@ -1073,7 +1073,7 @@ class LoginForm extends SpecialPage {
                }
 
                $currentUser = $this->getUser();
-               wfRunHooks( 'User::mailPasswordInternal', array( &$currentUser, &$ip, &$u ) );
+               Hooks::run( 'User::mailPasswordInternal', array( &$currentUser, &$ip, &$u ) );
 
                $np = $u->randomPassword();
                $u->setNewpassword( $np, $throttle );
@@ -1104,7 +1104,7 @@ class LoginForm extends SpecialPage {
                # Run any hooks; display injected HTML if any, else redirect
                $currentUser = $this->getUser();
                $injected_html = '';
-               wfRunHooks( 'UserLoginComplete', array( &$currentUser, &$injected_html ) );
+               Hooks::run( 'UserLoginComplete', array( &$currentUser, &$injected_html ) );
 
                if ( $injected_html !== '' ) {
                        $this->displaySuccessfulAction( 'success', $this->msg( 'loginsuccesstitle' ),
@@ -1126,14 +1126,14 @@ class LoginForm extends SpecialPage {
                $injected_html = '';
                $welcome_creation_msg = 'welcomecreation-msg';
 
-               wfRunHooks( 'UserLoginComplete', array( &$currentUser, &$injected_html ) );
+               Hooks::run( 'UserLoginComplete', array( &$currentUser, &$injected_html ) );
 
                /**
                 * Let any extensions change what message is shown.
                 * @see https://www.mediawiki.org/wiki/Manual:Hooks/BeforeWelcomeCreation
                 * @since 1.18
                 */
-               wfRunHooks( 'BeforeWelcomeCreation', array( &$welcome_creation_msg, &$injected_html ) );
+               Hooks::run( 'BeforeWelcomeCreation', array( &$welcome_creation_msg, &$injected_html ) );
 
                $this->displaySuccessfulAction(
                        'signup',
@@ -1243,7 +1243,7 @@ class LoginForm extends SpecialPage {
                }
 
                // Allow modification of redirect behavior
-               wfRunHooks( 'PostLoginRedirect', array( &$returnTo, &$returnToQuery, &$type ) );
+               Hooks::run( 'PostLoginRedirect', array( &$returnTo, &$returnToQuery, &$type ) );
 
                $returnToTitle = Title::newFromText( $returnTo );
                if ( !$returnToTitle ) {
@@ -1447,9 +1447,9 @@ class LoginForm extends SpecialPage {
                // Give authentication and captcha plugins a chance to modify the form
                $wgAuth->modifyUITemplate( $template, $this->mType );
                if ( $this->mType == 'signup' ) {
-                       wfRunHooks( 'UserCreateForm', array( &$template ) );
+                       Hooks::run( 'UserCreateForm', array( &$template ) );
                } else {
-                       wfRunHooks( 'UserLoginForm', array( &$template ) );
+                       Hooks::run( 'UserLoginForm', array( &$template ) );
                }
 
                $out->disallowUserJs(); // just in case...
index d65ac85..080dc11 100644 (file)
@@ -56,7 +56,7 @@ class SpecialUserlogout extends UnlistedSpecialPage {
 
                // Hook.
                $injected_html = '';
-               wfRunHooks( 'UserLogoutComplete', array( &$user, &$injected_html, $oldName ) );
+               Hooks::run( 'UserLogoutComplete', array( &$user, &$injected_html, $oldName ) );
                $out->addHTML( $injected_html );
 
                $out->returnToMain();
index 6ca57aa..3e9313c 100644 (file)
@@ -267,7 +267,7 @@ class UserrightsPage extends SpecialPage {
 
                wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) . "\n" );
                wfDebug( 'newGroups: ' . print_r( $newGroups, true ) . "\n" );
-               wfRunHooks( 'UserRights', array( &$user, $add, $remove ) );
+               Hooks::run( 'UserRights', array( &$user, $add, $remove ) );
 
                if ( $newGroups != $oldGroups ) {
                        $this->addLogEntry( $user, $oldGroups, $newGroups, $reason );
index 34f434f..ee9e2ad 100644 (file)
@@ -220,7 +220,7 @@ class SpecialVersion extends SpecialPage {
                $software[$dbr->getSoftwareLink()] = $dbr->getServerInfo();
 
                // Allow a hook to add/remove items.
-               wfRunHooks( 'SoftwareInfo', array( &$software ) );
+               Hooks::run( 'SoftwareInfo', array( &$software ) );
 
                $out = Xml::element(
                                'h2',
@@ -341,7 +341,7 @@ class SpecialVersion extends SpecialPage {
        private static function getwgVersionLinked() {
                global $wgVersion;
                $versionUrl = "";
-               if ( wfRunHooks( 'SpecialVersionVersionUrl', array( $wgVersion, &$versionUrl ) ) ) {
+               if ( Hooks::run( 'SpecialVersionVersionUrl', array( $wgVersion, &$versionUrl ) ) ) {
                        $versionParts = array();
                        preg_match( "/^(\d+\.\d+)/", $wgVersion, $versionParts );
                        $versionUrl = "https://www.mediawiki.org/wiki/MediaWiki_{$versionParts[1]}";
@@ -402,7 +402,7 @@ class SpecialVersion extends SpecialPage {
                                'other' => wfMessage( 'version-other' )->text(),
                        );
 
-                       wfRunHooks( 'ExtensionTypes', array( &self::$extensionTypes ) );
+                       Hooks::run( 'ExtensionTypes', array( &self::$extensionTypes ) );
                }
 
                return self::$extensionTypes;
index 16127d9..8a1a6c6 100644 (file)
@@ -99,7 +99,7 @@ class WantedFilesPage extends WantedQueryPage {
         * Use wfFindFile so we still think file namespace pages without
         * files are missing, but valid file redirects and foreign files are ok.
         *
-        * @return boolean
+        * @return bool
         */
        protected function existenceCheck( Title $title ) {
                return (bool)wfFindFile( $title );
index 38f1808..cad2348 100644 (file)
@@ -86,7 +86,7 @@ class WantedPagesPage extends WantedQueryPage {
                        )
                );
                // Replacement for the WantedPages::getSQL hook
-               wfRunHooks( 'WantedPages::getQueryInfo', array( &$this, &$query ) );
+               Hooks::run( 'WantedPages::getQueryInfo', array( &$this, &$query ) );
 
                return $query;
        }
index a7c2052..ca3386c 100644 (file)
@@ -123,7 +123,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
        protected function getCustomFilters() {
                if ( $this->customFilters === null ) {
                        $this->customFilters = parent::getCustomFilters();
-                       wfRunHooks( 'SpecialWatchlistFilters', array( $this, &$this->customFilters ), '1.23' );
+                       Hooks::run( 'SpecialWatchlistFilters', array( $this, &$this->customFilters ), '1.23' );
                }
 
                return $this->customFilters;
@@ -201,7 +201,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                } else {
                        # Top log Ids for a page are not stored
                        $nonRevisionTypes = array( RC_LOG );
-                       wfRunHooks( 'SpecialWatchlistGetNonRevisionTypes', array( &$nonRevisionTypes ) );
+                       Hooks::run( 'SpecialWatchlistGetNonRevisionTypes', array( &$nonRevisionTypes ) );
                        if ( $nonRevisionTypes ) {
                                $conds[] = $dbr->makeList(
                                        array(
@@ -286,7 +286,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                &$join_conds, $opts
        ) {
                return parent::runMainQueryHook( $tables, $fields, $conds, $query_options, $join_conds, $opts )
-                       && wfRunHooks(
+                       && Hooks::run(
                                'SpecialWatchlistQuery',
                                array( &$conds, &$tables, &$join_conds, &$fields, $opts ),
                                '1.23'
index e373cff..11ec363 100644 (file)
@@ -335,7 +335,7 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
                        $props[] = $msgcache['isimage'];
                }
 
-               wfRunHooks( 'WhatLinksHereProps', array( $row, $nt, $target, &$props ) );
+               Hooks::run( 'WhatLinksHereProps', array( $row, $nt, $target, &$props ) );
 
                if ( count( $props ) ) {
                        $propsText = $this->msg( 'parentheses' )
index a278652..4c96dc8 100644 (file)
@@ -150,7 +150,7 @@ abstract class UploadBase {
 
                // Give hooks the chance to handle this request
                $className = null;
-               wfRunHooks( 'UploadCreateFromRequest', array( $type, &$className ) );
+               Hooks::run( 'UploadCreateFromRequest', array( $type, &$className ) );
                if ( is_null( $className ) ) {
                        $className = 'UploadFrom' . $type;
                        wfDebug( __METHOD__ . ": class name: $className\n" );
@@ -335,7 +335,7 @@ abstract class UploadBase {
                }
 
                $error = '';
-               if ( !wfRunHooks( 'UploadVerification',
+               if ( !Hooks::run( 'UploadVerification',
                        array( $this->mDestName, $this->mTempPath, &$error ) )
                ) {
                        wfProfileOut( __METHOD__ );
@@ -469,7 +469,7 @@ abstract class UploadBase {
                        }
                }
 
-               wfRunHooks( 'UploadVerifyFile', array( $this, $mime, &$status ) );
+               Hooks::run( 'UploadVerifyFile', array( $this, $mime, &$status ) );
                if ( $status !== true ) {
                        wfProfileOut( __METHOD__ );
 
@@ -755,7 +755,7 @@ abstract class UploadBase {
                                        WatchedItem::IGNORE_USER_RIGHTS
                                );
                        }
-                       wfRunHooks( 'UploadComplete', array( &$this ) );
+                       Hooks::run( 'UploadComplete', array( &$this ) );
 
                        $this->postProcessUpload();
                }
index b605640..14a6da6 100644 (file)
@@ -118,7 +118,7 @@ class UploadFromUrl extends UploadBase {
        public static function isAllowedUrl( $url ) {
                if ( !isset( self::$allowedUrls[$url] ) ) {
                        $allowed = true;
-                       wfRunHooks( 'IsUploadAllowedFromUrl', array( $url, &$allowed ) );
+                       Hooks::run( 'IsUploadAllowedFromUrl', array( $url, &$allowed ) );
                        self::$allowedUrls[$url] = $allowed;
                }
 
index 77f9cd1..55a8994 100644 (file)
@@ -717,7 +717,7 @@ class IP {
         */
        public static function isTrustedProxy( $ip ) {
                $trusted = self::isConfiguredProxy( $ip );
-               wfRunHooks( 'IsTrustedProxy', array( &$ip, &$trusted ) );
+               Hooks::run( 'IsTrustedProxy', array( &$ip, &$trusted ) );
                return $trusted;
        }
 
index fb04255..9e3abb3 100644 (file)
@@ -500,7 +500,7 @@ class Language {
                        # Re-order by namespace ID number...
                        ksort( $this->namespaceNames );
 
-                       wfRunHooks( 'LanguageGetNamespaces', array( &$this->namespaceNames ) );
+                       Hooks::run( 'LanguageGetNamespaces', array( &$this->namespaceNames ) );
                }
 
                return $this->namespaceNames;
@@ -898,7 +898,7 @@ class Language {
 
                if ( $inLanguage ) {
                        # TODO: also include when $inLanguage is null, when this code is more efficient
-                       wfRunHooks( 'LanguageGetTranslatedLanguageNames', array( &$names, $inLanguage ) );
+                       Hooks::run( 'LanguageGetTranslatedLanguageNames', array( &$names, $inLanguage ) );
                }
 
                $mwNames = $wgExtraLanguageNames + $coreLanguageNames;
@@ -3162,7 +3162,7 @@ class Language {
                }
                $this->mMagicHookDone = true;
                wfProfileIn( 'LanguageGetMagic' );
-               wfRunHooks( 'LanguageGetMagic', array( &$this->mMagicExtensions, $this->getCode() ) );
+               Hooks::run( 'LanguageGetMagic', array( &$this->mMagicExtensions, $this->getCode() ) );
                wfProfileOut( 'LanguageGetMagic' );
        }
 
@@ -3218,7 +3218,7 @@ class Language {
                        // Initialise array
                        $this->mExtendedSpecialPageAliases =
                                self::$dataCache->getItem( $this->mCode, 'specialPageAliases' );
-                       wfRunHooks( 'LanguageGetSpecialPageAliases',
+                       Hooks::run( 'LanguageGetSpecialPageAliases',
                                array( &$this->mExtendedSpecialPageAliases, $this->getCode() ) );
                }
 
@@ -4261,7 +4261,7 @@ class Language {
        public static function getMessagesFileName( $code ) {
                global $IP;
                $file = self::getFileName( "$IP/languages/messages/Messages", $code, '.php' );
-               wfRunHooks( 'Language::getMessagesFileName', array( $code, &$file ) );
+               Hooks::run( 'Language::getMessagesFileName', array( $code, &$file ) );
                return $file;
        }
 
index f9b6495..1b350c0 100644 (file)
        "anoneditwarning": "<strong>Папярэджаньне</strong>: вы не ўвайшлі ў сыстэму. Ваш IP-адрас будзе бачны ўсім, калі вы адрэдагуеце старонку. Калі вы <strong>[$1 ўвойдзеце]</strong> або <strong>[$2 створыце рахунак]</strong>, вашыя рэдагаваньні будуць зьвязаныя з вашым імем карыстальніка, а таксама вам будуць даступныя дадатковыя перавагі.",
        "anonpreviewwarning": "''Вы не ўвайшлі ў сыстэму. Падчас захаваньня Ваш IP-адрас будзе дададзены ў гісторыю рэдагаваньняў старонкі.''",
        "missingsummary": "'''Напамін:''' Вы не пазначылі кароткае апісаньне зьменаў.\nКалі Вы націсьніце кнопку «Запісаць» яшчэ раз, Вашае рэдагаваньне будзе запісанае без апісаньня.",
+       "selfredirect": "<strong>Папярэджаньне:</strong> вы ствараеце перанакіраваньне на гэты самы артыкул.\nКалі вы націсьніце «{{int:savearticle}}» яшчэ раз, перанакіраваньне будзе створанае.",
        "missingcommenttext": "Калі ласка, увядзіце камэнтар ніжэй.",
        "missingcommentheader": "'''Напамін:''' Вы не пазначылі загаловак камэнтара.\nКалі Вы націсьніце кнопку «{{int:savearticle}}» яшчэ раз, Ваш камэнтар захаваецца бяз тэмы.",
        "summary-preview": "Папярэдні прагляд апісаньня:",
index b111bf5..d7d71e6 100644 (file)
@@ -49,7 +49,7 @@
        "tog-shownumberswatching": "নজরদারী করছে, এমন ব্যবহারকারীর সংখ্যা দেখানো হোক",
        "tog-oldsig": "বর্তমান স্বাক্ষর:",
        "tog-fancysig": "স্বাক্ষরকে উইকিটেক্সট হিসেবে মনে করুন (কোন সয়ংক্রিয় লিঙ্ক ছাড়া)",
-       "tog-uselivepreview": "তাৎক্ষণিক প্রাকদর্শনের ক্ষমতা চালু করা হোক (পরীক্ষামূলক)",
+       "tog-uselivepreview": "তাৎক্ষণিক প্রাকদর্শন ব্যবহার করো",
        "tog-forceeditsummary": "খালি সম্পাদনা সারাংশ প্রবেশ করানোর সময় আমাকে জানানো হোক",
        "tog-watchlisthideown": "আমার সম্পাদনাগুলি আমার নজরতালিকায় না দেখানো হোক",
        "tog-watchlisthidebots": "বটের করা সম্পাদনাগুলি নজরতালিকায় না দেখানো হোক",
        "showhideselectedversions": "নির্বাচিত সংশোধনগুলো দেখাও/লুকাও",
        "editundo": "পূর্বাবস্থায় আনো",
        "diff-empty": "(কোন পার্থক্য নেই)",
+       "diff-multi-sameuser": "(একই ব্যবহারকারী দ্বারা সম্পাদিত {{PLURAL:$1|একটি মধ্যবর্তী সংশোধন|$1টি মধ্যবর্তী সংশোধন}} দেখানো হচ্ছে না)",
+       "diff-multi-otherusers": "({{PLURAL:$2|একজন|$2 জন}} ব্যবহারকারী দ্বারা সম্পাদিত {{PLURAL:$1|একটি|$1টি}} মধ্যবর্তী সংশোধন দেখানো হচ্ছে না)",
        "diff-multi-manyusers": "($2 জন {{PLURAL:$2|ব্যবহারাকারীর}} সম্পাদিত {{PLURAL:$1|একটি সাম্প্রতিক সংস্করণ|$1 টি সাম্প্রতিক সংস্করণ}} প্রদর্শিত হচ্ছে না)",
        "difference-missing-revision": "$1 পার্থক্যের {{PLURAL:$2|একটি সংস্করণ|$2টি সংস্করণসমূহ}} খুজে পাওয়া যাচ্ছে না।\n\nসাধারণত মুছে ফেলা হয়েছে এমন পাতার মেয়াদ উত্তীর্ণ ইতিহাস পাতার লিংক ওপেন করার কারণে এটি হতে পারে। \n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} অপসারণ লগে] বিস্তারিত তথ্য জানা যাবে।",
        "searchresults": "অনুসন্ধানের ফলাফল",
index 69b38ea..7f11733 100644 (file)
@@ -45,7 +45,7 @@
        "tog-shownumberswatching": "Prikaži broj korisnika koji prate",
        "tog-oldsig": "Postojeći potpis:",
        "tog-fancysig": "Smatraj potpis kao wikitekst (bez automatskog linka)",
-       "tog-uselivepreview": "Koristite pregled uživo (eksperimentalno)",
+       "tog-uselivepreview": "Koristite pregled uživo",
        "tog-forceeditsummary": "Opomeni me pri unosu praznog sažetka",
        "tog-watchlisthideown": "Sakrij moje izmjene sa spiska praćenih članaka",
        "tog-watchlisthidebots": "Sakrij izmjene botova sa spiska praćenih članaka",
        "december-date": "$1. decembar",
        "pagecategories": "{{PLURAL:$1|Kategorija|Kategorije}}",
        "category_header": "Članci u kategoriji \"$1\"",
-       "subcategories": "Potkategorije",
+       "subcategories": "Podkategorije",
        "category-media-header": "Datoteke u kategoriji \"$1\"",
        "category-empty": "''Ova kategorija trenutno ne sadrži članke ni medije.''",
        "hidden-categories": "{{PLURAL:$1|Sakrivena kategorija|Sakrivene kategorije}}",
-       "hidden-category-category": "Sakrivene kategorije",
+       "hidden-category-category": "Skrivene kategorije",
        "category-subcat-count": "{{PLURAL:$2|Ova kategorija ima sljedeću podkategoriju.|Ova kategorija ima {{PLURAL:$1|sljedeću podkategoriju|sljedeće $1 podkategorije|sljedećih $1 podkategorija}}, od $2 ukupno.}}",
        "category-subcat-count-limited": "Ova kategorija sadrži {{PLURAL:$1|slijedeću $1 podkategoriju|slijedeće $1 podkategorije|slijedećih $1 podkategorija}}.",
        "category-article-count": "{{PLURAL:$2|U ovoj kategoriji nalazi se $1 članak.|{{PLURAL:$1|Prikazan je $1 članak|Prikazana su $1 članka|Prikazano je $1 članaka}} od ukupno $2 u ovoj kategoriji.}}",
        "otherlanguages": "Na drugim jezicima",
        "redirectedfrom": "(Preusmjereno sa $1)",
        "redirectpagesub": "Preusmjeri stranicu",
+       "redirectto": "Preusmjerenje na:",
        "lastmodifiedat": "Ova stranica je posljednji put izmijenjena $2, $1",
        "viewcount": "Ovoj stranici je pristupljeno {{PLURAL:$1|$1 put|$1 puta}}.",
        "protectedpage": "Zaštićena stranica",
        "filerenameerror": "Ne može se promjeniti ime datoteke \"$1\" u \"$2\".",
        "filedeleteerror": "Ne može se izbrisati datoteka \"$1\".",
        "directorycreateerror": "Nije moguće napraviti direktorijum \"$1\".",
+       "directorynotreadableerror": "Direktorij \"$1\" nije čitljiv.",
        "filenotfound": "Ne može se naći datoteka \"$1\".",
        "unexpected": "Neočekivana vrijednost: \"$1\"=\"$2\".",
        "formerror": "Greška: ne može se poslati upitnik",
        "createacct-imgcaptcha-ph": "Unesite tekst koji vidite iznad",
        "createacct-submit": "Napravite svoj korisnički račun",
        "createacct-another-submit": "Napravi još jedan korisnički račun",
-       "createacct-benefit-heading": "{{SITENAME}} je napravljen od strane ljudi kao što ste Vi.",
+       "createacct-benefit-heading": "{{SITENAME}} je napravljena od strane ljudi kao što ste Vi.",
        "createacct-benefit-body1": "{{PLURAL:$1|izmjena|izmjene}}",
        "createacct-benefit-body2": "{{PLURAL:$1|stranica|stranice|stranica}}",
-       "createacct-benefit-body3": "nedavni {{PLURAL:$1|doprinosa}}",
+       "createacct-benefit-body3": "nedavnih {{PLURAL:$1|doprinosa}}",
        "badretype": "Šifre koje ste unijeli se ne poklapaju.",
        "userexists": "Korisničko ime koje ste unijeli je već u upotrebi.\nMolimo Vas da izaberete drugo ime.",
        "loginerror": "Greška pri prijavljivanju",
        "accountcreated": "Korisnički račun je napravljen",
        "accountcreatedtext": "Korisnički račun za [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|razgovor]]) je napravljen.",
        "createaccount-title": "Pravljenje korisničkog računa za {{SITENAME}}",
-       "createaccount-text": "Neko je napravio korisnički račun za vašu e-mail adresu na {{SITENAME}} ($4) sa imenom \"$2\", i sa šifrom \"$3\".\nTrebali biste se prijaviti i promjeniti šifru.\n\nMožete ignorisati ovu poruku, ako je korisnički račun napravljen greškom.",
+       "createaccount-text": "Neko je napravio korisnički račun za vašu e-mail adresu na {{SITENAME}} ($4) sa imenom \"$2\", i sa šifrom \"$3\".\nTrebali biste se prijaviti i promijeniti šifru.\n\nMožete ignorisati ovu poruku, ako je korisnički račun napravljen greškom.",
        "login-throttled": "Previše puta ste se pokušali prijaviti.\nMolimo Vas da sačekate $1 prije nego što pokušate ponovo.",
        "login-abort-generic": "Vaša prijava nije bila uspješna – Prekinuto",
        "loginlanguagelabel": "Jezik: $1",
        "revdelete-hide-text": "Tekst revizije",
        "revdelete-hide-image": "Sakrij sadržaj datoteke",
        "revdelete-hide-name": "Sakrij akciju i cilj",
-       "revdelete-hide-comment": "Sakrij izmjene komentara",
+       "revdelete-hide-comment": "Uredi sažetak",
        "revdelete-hide-user": "Korisničko ime urednika/IP",
        "revdelete-hide-restricted": "Ograniči podatke za administratore kao i za druge korisnike",
        "revdelete-radio-same": "(ne mijenjaj)",
        "search-result-category-size": "{{PLURAL:$1|1 član|$1 člana|$1 članova}} ({{PLURAL:$2|1 podkategorija|$2 podkategorije|$2 podkategorija}}, {{PLURAL:$3|1 datoteka|$3 datoteke|$3 datoteka}})",
        "search-redirect": "(preusmjeravanje $1)",
        "search-section": "(sekcija $1)",
+       "search-category": "(kategorija $1)",
        "search-suggest": "Da li ste mislili: $1",
        "search-interwiki-caption": "Srodni projekti",
        "search-interwiki-default": "$1 rezultati:",
        "invalid-chunk-offset": "Neispravna polazna tačka",
        "img-auth-accessdenied": "Pristup onemogućen",
        "img-auth-nopathinfo": "Nedostaje PATH_INFO.\nVaš server nije postavljen da daje ovu informaciju.\nMožda je zasnovan na CGI koji ne podržava img_auth.\nPogledajte https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
-       "img-auth-notindir": "Zahtjevana putanje nije u direktorijumu podešenom za postavljanje.",
+       "img-auth-notindir": "Zahtjevana putanja nije u direktoriju podešenom za postavljanje.",
        "img-auth-badtitle": "Ne mogu napraviti valjani naslov iz \"$1\".",
        "img-auth-nologinnWL": "Niste prijavljeni i \"$1\" nije na spisku dozvoljenih.",
        "img-auth-nofile": "Datoteka \"$1\" ne postoji.",
-       "img-auth-isdir": "Pokušavate pristupiti direktorijumu \"$1\".\nDozvoljen je samo pristup datotekama.",
+       "img-auth-isdir": "Pokušavate pristupiti direktoriju \"$1\".\nDozvoljen je samo pristup datotekama.",
        "img-auth-streaming": "Tok \"$1\".",
        "img-auth-public": "Funkcija img_auth.php služi za izlaz datoteka sa privatnih wikija.\nOva wiki je postavljena kao javna wiki.\nZa optimalnu sigurnost, img_auth.php je onemogućena.",
        "img-auth-noread": "Korisnik nema pristup za čitanje \"$1\".",
        "querypage-disabled": "Ova posebna stranica je onemogućena jer smanjuje performanse.",
        "booksources": "Štampani izvori",
        "booksources-search-legend": "Traži književne izvore",
+       "booksources-search": "Traži",
        "booksources-text": "Ispod se nalazi spisak vanjskih linkova na ostale stranice koje prodaju nove ili korištene knjige kao i stranice koje mogu da imaju važnije podatke o knjigama koje tražite:",
        "booksources-invalid-isbn": "Navedeni ISBN broj nije validan; molimo da provjerite da li je došlo do greške pri kopiranju iz prvobitnog izvora.",
        "specialloguserlabel": "Izvršilac:",
        "listgrouprights-addgroup-self-all": "Može dodati sve grupe na svoj račun",
        "listgrouprights-removegroup-self-all": "Može ukloniti sve grupe sa svog računa",
        "listgrouprights-namespaceprotection-namespace": "Imenski prostor",
+       "trackingcategories-name": "Ime poruke",
        "trackingcategories-nodesc": "Opis nije dostupan.",
        "mailnologin": "Nema adrese za slanje",
        "mailnologintext": "Morate biti [[Special:UserLogin|prijavljeni]]\ni imati ispravnu adresu e-pošte u vašim [[Special:Preferences|podešavanjima]]\nda biste slali e-poštu drugim korisnicima.",
        "tooltip-feed-atom": "Atom za ovu stranicu",
        "tooltip-t-contributions": "Pogledajte spisak doprinosa ovog korisnika",
        "tooltip-t-emailuser": "Pošaljite pismo ovom korisniku",
+       "tooltip-t-info": "Više informacija o ovoj stranici",
        "tooltip-t-upload": "Postavi slike i druge medije",
        "tooltip-t-specialpages": "Spisak svih posebnih stranica",
        "tooltip-t-print": "Verzija ove stranice za štampanje",
        "confirm-watch-top": "Dodajte ovu stranu na Vaš spisak praćenih članaka",
        "confirm-unwatch-button": "U redu",
        "confirm-unwatch-top": "Izbrišite ovu stranu sa Vašeg spiska praćenih članaka",
+       "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← prethodna stranica",
        "imgmultipagenext": "slijedeća stranica →",
        "imgmultigo": "Idi!",
        "imgmultigoto": "Idi na stranicu $1",
+       "img-lang-default": "(podrazumijevani jezik)",
+       "img-lang-info": "Prikaži ovu sliku u $1. $2",
        "img-lang-go": "Idi",
        "ascending_abbrev": "rast",
        "descending_abbrev": "opad",
        "autosumm-replace": "Zamjena stranice sa '$1'",
        "autoredircomment": "Preusmjereno na [[$1]]",
        "autosumm-new": "Napravljena stranica sa '$1'",
+       "autosumm-newblank": "Napravljena prazna stranica",
        "size-bytes": "$1 B",
        "size-kilobytes": "$1 KB",
        "size-megabytes": "$1 MB",
        "watchlistedit-raw-done": "Vaš spisak praćenja je ažuriran.",
        "watchlistedit-raw-added": "{{PLURAL:$1|1 naslov je dodan|$1 naslova su dodana|$1 naslova je dodano}}:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|1 naslov je uklonjen|$1 naslova je uklonjeno}}:",
+       "watchlisttools-clear": "Očisti spisak nadgledanja",
        "watchlisttools-view": "Pregled promjena praćenih stranica",
        "watchlisttools-edit": "Pogledaj i uredi listu praćenih članaka.",
        "watchlisttools-raw": "Uređivanje praćenih stranica u okviru praćenja.",
        "version-version": "(Verzija $1)",
        "version-license": "Licenca",
        "version-ext-license": "Licenca",
+       "version-ext-colheader-name": "Proširenje",
+       "version-skin-colheader-name": "Izgled",
        "version-ext-colheader-version": "Verzija",
        "version-ext-colheader-license": "Licenca",
        "version-ext-colheader-description": "Opis",
        "specialpages-group-wiki": "Podaci i alati",
        "specialpages-group-redirects": "Preusmjeravanje posebnih stranica",
        "specialpages-group-spam": "Alati za spam",
+       "specialpages-group-developer": "Razvojni alati",
        "blankpage": "Prazna stranica",
        "intentionallyblankpage": "Ova stranica je namjerno ostavljena prazna",
        "external_image_whitelist": " #Ostavite ovu liniju onakva kakva je<pre>\n#Stavite obične fragmente opisa (samo dio koji ide između //) ispod\n#Ovi će biti spojeni sa URLovima sa vanjskih (eksternih) slika\n#One koji se spoje biće prikazane kao slike, u suprotnom će se prikazati samo link\n#Linije koje počinju sa # se tretiraju kao komentari\n#Ovo ne razlikuje velika i mala slova\n\n#Stavite sve regex fragmente iznad ove linije. Ostavite ovu liniju onakvu kakva je</pre>",
        "duration-centuries": "$1 {{PLURAL:$1|vijek|vijeka|vijekova}}",
        "duration-millennia": "$1 {{PLURAL:$1|milenij|milenija}}",
        "rotate-comment": "Slika rotirana za $1 {{PLURAL:$1|stepen|stepeni}} u smjeru kazaljke na satu",
+       "limitreport-walltime": "Korištenje u realnom vremenu",
        "limitreport-walltime-value": "$1 {{PLURAL:$1|sekunda|sekunde|sekundi}}",
        "expandtemplates": "Proširi šablone",
        "expand_templates_intro": "Ova posebna stranica uzima neki tekst i proširuje sve šablone u njemu rekurzivno.\nOna također proširuje parserske funkcije poput\n<nowiki>{{</nowiki>#language:…}} i varijable poput\n<nowiki>{{</nowiki>CURRENTDAY}}&mdash;u principu gotovo sve između dvostrukih zagrada.\nOvo se uradi putem poziva relevantnog parserskog nivoa iz same MediaWiki.",
        "expand_templates_preview": "Pregled",
        "pagelang-name": "Stranica",
        "pagelang-language": "Jezik",
-       "pagelang-select-lang": "Izaberi jezik"
+       "pagelang-select-lang": "Izaberi jezik",
+       "mediastatistics-header-unknown": "Nepoznato",
+       "json-error-syntax": "Sintaksna greška"
 }
index 05c0e9d..180a185 100644 (file)
@@ -35,7 +35,7 @@
        "tog-enotifrevealaddr": "Гайта сан зlе оцу хаамаш барехь",
        "tog-shownumberswatching": "Гайта декъашхойн терахь, агӀо латийна болу шай тергаме могӀанан юкъа",
        "tog-oldsig": "Карара куьгтаӀорна:",
-       "tog-fancysig": "Шен Ð²Ð¸ÐºÐ¸-кÑ\8aаÑ\81Ñ\82аман ÐºÑ\83Ñ\8cгÑ\82аÓ\80даÑ\80 (Ñ\88а Ñ\88еÑ\85 Ñ\85Ñ\8cажоÑ\80аг Ð¹Ð¾Ñ\86Ñ\83Ñ\88)",
+       "tog-fancysig": "Шен вики-къастаман куьгтаӀдар (ша шех хьажорг йоцуш)",
        "tog-uselivepreview": "Лелайа чехка хьалха хьажа (JavaScript, муха ю хьажарна)",
        "tog-forceeditsummary": "Дага даийта, нагахь нисйарх лаьцна чохь язйина яцахь",
        "tog-watchlisthideown": "Къайлаяха ас нисйинарш тергаме могӀам чура",
        "history_short": "Истори",
        "updatedmarker": "Керла яккхина сона гинчултӀаьхьа",
        "printableversion": "Зорба туху верси",
-       "permalink": "Ð\94аиман Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cажоÑ\80аг",
+       "permalink": "Даиман йолу хьажорг",
        "print": "Зорба тоха",
        "view": "Хьажа",
        "view-foreign": "Сайтехь $1 хьажа",
        "readonly": "Блоктоьхна дӀайаздар хаамийн бухе",
        "enterlockreason": "Билгалде блоктохаран бахьна а и чекх йолу хан а.",
        "readonlytext": "АгӀонаш тӀетохар а кхин хийцамаш барна а блоктоьхна:\nБлокоьхначо биттина хаам: $1.",
-       "missing-article": "Ð¥Ó\80окÑ\85Ñ\83 Ñ\87оÑ\85Ñ\8c ÐºÐ°Ñ\80оезаÑ\88 Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cан Ð´ÐµÑ\85аÑ\80Ñ\86а Ð¹Ð¾Ð·Ð°Ð½ Ð°Ð³Ó\80онаÑ\88 Ñ\86акаÑ\80ийна Â«$1» $2.\n\nÐ\98Ñ\88Ñ\82наÑ\80г Ð½Ð°Ð³Ð³Ð°Ñ\85Ñ\8c Ñ\85Ñ\83Ñ\8cлÑ\83 Ñ\85Ñ\8cажоÑ\80аг Ð´Ó\80аÑ\8fÑ\8cккÑ\85ина ÐµÐ»Ð°Ñ\85Ñ\8c Ñ\8f Ñ\85ийÑ\86ам Ð±Ð¸Ð½Ð° Ñ\82иÑ\88а Ñ\85Ñ\8cажоÑ\80агца дехьа гӀо гӀоьртича.\n\nНагахьсан гӀулкх цуьнах доьзна дацахь, хьуна карийна гӀирс латточехь гӀалат.\nДехар до, хаам бе оцуьнах [[Special:ListUsers/sysop|куьйгалхога]], гойтуш URL.",
+       "missing-article": "Ð¥Ó\80окÑ\85Ñ\83 Ñ\87оÑ\85Ñ\8c ÐºÐ°Ñ\80оезаÑ\88 Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cан Ð´ÐµÑ\85аÑ\80Ñ\86а Ð¹Ð¾Ð·Ð°Ð½ Ð°Ð³Ó\80онаÑ\88 Ñ\86акаÑ\80ийна Â«$1» $2.\n\nÐ\98Ñ\88Ñ\82наÑ\80г Ð½Ð°Ð³Ð³Ð°Ñ\85Ñ\8c Ñ\85Ñ\83Ñ\8cлÑ\83 Ñ\85Ñ\8cажоÑ\80г Ð´Ó\80аÑ\8fÑ\8cккÑ\85ина ÐµÐ»Ð°Ñ\85Ñ\8c Ñ\8f Ñ\85ийÑ\86ам Ð±Ð¸Ð½Ð° Ñ\82иÑ\88а Ñ\85Ñ\8cажоÑ\80гца дехьа гӀо гӀоьртича.\n\nНагахьсан гӀулкх цуьнах доьзна дацахь, хьуна карийна гӀирс латточехь гӀалат.\nДехар до, хаам бе оцуьнах [[Special:ListUsers/sysop|куьйгалхога]], гойтуш URL.",
        "missingarticle-rev": "(верси № $1)",
        "missingarticle-diff": "(башхалла: $1, $2)",
        "readonly_lag": "Хаамашан базина цхьана хан блоктоьхна, хаамашан базан сервераш нисялца.",
        "italic_sample": "Сеттан до йоза",
        "italic_tip": "Сеттан до йоза",
        "link_sample": "Хьажориган коьрта могlа",
-       "link_tip": "ЧоÑ\8cÑ\85Ñ\8cа Ñ\85Ñ\8cажоÑ\80аг",
-       "extlink_sample": "http://www.example.com Ñ\85Ñ\8cажоÑ\80аг ÐºÐ¾Ñ\80Ñ\82а",
-       "extlink_tip": "Ð\90Ñ\80аÑ\85Ñ\8cаÑ\80а Ñ\85Ñ\8cажоÑ\80аг (йиÑ\86 Ð¼Ð° Ð¹Ðµ Ñ\85Ó\80оÑ\82Ñ\82алÑ\83Ñ\88еÑ\80г http://)",
+       "link_tip": "Чоьхьа хьажорг",
+       "extlink_sample": "http://www.example.com хьажорг корта",
+       "extlink_tip": "Арахьара хьажорг (йиц ма йе хӀотталушерг http://)",
        "headline_sample": "Йозан корта",
        "headline_tip": "Корта 2-гlа локхаллийца",
        "nowiki_sample": "Чудиллийша кхузе барамхlоттонза йоза.",
        "image_sample": "Example.jpg",
        "image_tip": "Чохь йолу файл",
        "media_sample": "Example.ogg",
-       "media_tip": "Ð¥Ñ\8cажоÑ\80аг Ð¼ÐµÐ´Ð¸Ð°-Ñ\84айлан Ñ\82Ó\80е",
+       "media_tip": "Хьажорг медиа-файлан тӀе",
        "sig_tip": "Хьан куьгтаlор аъ хlоттина хан",
        "hr_tip": "Ана сиз (сих сиха ма леладайша)",
        "summary": "Хийцамех лаьцна:",
        "note": "'''Билгалдаккхар:'''",
        "previewnote": "'''ХӀара хьлха хьажар ду, йоза хӀинца язданза ду!'''",
        "continue-editing": "Кхин дӀа тадар",
-       "session_fail_preview": "СеÑ\80веÑ\80 Ð»Ð°Ñ\80а Ñ\86а Ð¹Ð¸Ñ\80а Ð°Ñ\85Ñ\8cа Ð±Ð¸Ð½Ð° Ñ\85ийÑ\86амаÑ\88 Ð´Ó\80аÑ\8fзба. Ð\9aÑ\85иÑ\8a Ñ\86кÑ\8aа Ð° Ð³Ó\80оÑ\80Ñ\82аÑ\85Ñ\8c.\nÐ\9dагаÑ\85Ñ\8c Ñ\81анна Ñ\85Ó\80аÑ\80а Ð³Ó\80алаÑ\82 Ñ\8eÑ\85а Ð° Ð´Ð°Ð»Ð°Ñ\85Ñ\8c, [[Special:UserLogout|Ñ\81еанÑ\81 Ð´Ó\80а Ð° ÐºÑ\8aоÑ\8cвлин]], Ñ\8eÑ\85а Ð° Ñ\81иÑ\81Ñ\82емин Ñ\87Ñ\83вала/Ñ\8fла Ñ\85Ñ\8cажа.",
+       "session_fail_preview": "СеÑ\80веÑ\80 Ð»Ð°Ñ\80а Ñ\86а Ð¹Ð¸Ñ\80а Ð°Ñ\85Ñ\8cа Ð±Ð¸Ð½Ð° Ñ\85ийÑ\86амаÑ\88 Ð´Ó\80аÑ\8fзба. Ð\9aÑ\85иÑ\8a Ñ\86кÑ\8aа Ð° Ð³Ó\80оÑ\80Ñ\82аÑ\85Ñ\8c.\nÐ\9dагаÑ\85Ñ\8c Ñ\81анна Ñ\85Ó\80аÑ\80а Ð³Ó\80алаÑ\82 Ñ\8eÑ\85а Ð° Ð´Ð°Ð»Ð°Ñ\85Ñ\8c, [[Special:UserLogout|Ñ\81еанÑ\81 Ð´Ó\80а Ð° ÐºÑ\8aоÑ\8cвлин]], Ñ\8eÑ\85а Ð° Ñ\81иÑ\81Ñ\82емин Ñ\87Ñ\83гÓ\80о.",
        "edit_form_incomplete": "'''Цхьайолу тадаран формаш серверан тӀекхаьчча яц. Тидаме хьажа хьай нисдарш доьхна дуй, ТӀакха южу гӀорта.'''",
        "editing": "Тадар: $1",
        "creating": "АгӀо кхоллар «$1»",
        "searchall": "массо",
        "showingresults": "Лахахьа {{PLURAL:$1|гойту}} <strong>$1</strong> {{PLURAL:$1|хилам}}, дӀаболало кху № <strong>$2</strong>.",
        "showingresultsinrange": "Лахахь гайтина {{PLURAL:$1|<strong>1</strong> хилам}} диапазонехь <strong>$2</strong> тӀера <strong>$3</strong> кхаччалц.",
-       "search-showingresults": "{{PLURAL:$4|Карийнарш <strong>$1</strong> чура <strong>$3</strong>|Карийнарш <strong>$1 — $2</strong> чура <strong>$3</strong>}}",
+       "search-showingresults": "{{PLURAL:$4|Карийна <strong>$1</strong> — цхьаъ агӀо|Карийна <strong>$3</strong> агӀо, царах агӀонгахь гойту $2 агӀо}}",
        "search-nonefound": "Дехаре терра цхьа хӀума ца карийна.",
        "powersearch-legend": "Шуьйра лахар",
        "powersearch-ns": "ЦӀерийн меттигашкахь лахар:",
        "recentchangeslinked-title": "Кхуьнца долу нисдарш $1",
        "recentchangeslinked-summary": "ХӀара хийцам биначу агӀонийн могӀам бу, тӀетовжар долуш хьагучу агӀон (я хьагойтуш йолучу категорена).\nАгӀонаш юькъа йогӀуш йолу хьан [[Special:Watchlist|тергаме могӀам чохь]] '''къастийна ю'''.",
        "recentchangeslinked-page": "АгӀон цӀе:",
-       "recentchangeslinked-to": "Ð\9aÑ\85еÑ\87Ñ\83 Ð°Ð³Ó\80оÑ\80, Ð³Ð°Ð¹Ñ\82а Ñ\85ийÑ\86амаÑ\88 Ð°Ð³Ó\80онаÑ\88Ñ\86а, Ñ\85Ó\80оÑ\82Ñ\82ийнаÑ\87Ñ\83 Ð°Ð³Ó\80онÑ\82Ó\80е Ñ\85Ñ\8cажоÑ\80аг Ð¹Ð¾Ð»Ñ\83Ñ\88",
+       "recentchangeslinked-to": "Кхечу агӀор, гайта хийцамаш агӀонашца, хӀоттийначу агӀонтӀе хьажорг йолуш",
        "upload": "Файл чуяккхар",
        "uploadbtn": "Файл чуяккхар",
        "reuploaddesc": "Юху гӀо файл чуйоккху агӀоне",
        "uploadnologintext": "Серверан чу файлаш яха хьо $1.",
        "uploaderror": "Файл чуяккхаран гӀалат",
        "upload-recreate-warning": "'''Тегам бе: иштта цӀе йолу файл дӀаяьккхина я цӀе хийцина.'''\n\nЛахахьа гойтуш ю хӀокху агӀона тептар:",
-       "uploadtext": "Ð\9bелайе Ñ\85Ó\80аÑ\80а Ð°Ð³Ó\80о Ñ\81еÑ\80веÑ\80 Ñ\87Ñ\83 Ñ\84айлаÑ\88 Ð¹Ð¾Ñ\85Ñ\83Ñ\88.\nÐ¥Ñ\8cалÑ\85о Ñ\87Ñ\83Ñ\8fÑ\8cÑ\85на Ñ\84айлаÑ\88 Ñ\85Ñ\8cажа,  [[Special:FileList|кÑ\85Ñ\83заÑ\85Ñ\8c]]. Ð\9aÑ\85ин Ñ\87Ñ\83Ñ\8fÑ\8cÑ\85на Ñ\84айлаÑ\88 Ð´Ó\80аÑ\8fзло [[Special:Log/upload|Ñ\87Ñ\83Ñ\8fÑ\85аÑ\80ан Ñ\82епÑ\82аÑ\80 Ñ\87оÑ\85Ñ\8c]], Ð´Ó\80аÑ\8fÑ\8cÑ\85на Ñ\84айлаÑ\88 ÐºÐ°Ñ\80о Ð¹Ð¸Ñ\88 Ñ\8e [[Special:Log/delete|кÑ\85Ñ\83заÑ\85Ñ\8c]].\n\nФайл Ð°Ð³Ó\80она Ñ\87Ñ\83йилла Ð»ÐµÐ»Ð°Ð±Ðµ Ð»Ð°Ñ\85аÑ\80а Ð¼Ð¾Ð³Ó\80анаÑ\88:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code>''' Ñ\84айла Ð¤Ð°Ð¹Ð»Ð°Ð½ Ñ\8eÑ\8cззина Ð²ÐµÑ\80Ñ\81и Ñ\87Ñ\83йиллÑ\83Ñ\88;\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|Ñ\86Ñ\83наÑ\85Ñ\8c Ð»Ð°Ñ\8cÑ\86на Ñ\85аам]]</nowiki></code>''' 200 Ð¿Ð¸ÐºÑ\81елÑ\8c Ð±Ð°Ñ\80амеÑ\85Ñ\8c Ñ\84айл Ñ\87Ñ\83йилаÑ\80 Ð±Ñ\83Ñ\85аÑ\85Ñ\8c Ñ\86Ñ\83наÑ\85Ñ\8c Ð»Ð°Ñ\8cÑ\86на Ð¼Ð¾Ð³Ó\80а Ð° Ð±Ð¾Ð»Ñ\83Ñ\88;\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' Ñ\84айлан Ñ\82Ó\80е Ñ\85Ñ\8cажоÑ\80аг Ñ\85Ó\80оÑ\82айо Ñ\84айл Ð°Ð³Ó\80онгаÑ\85Ñ\8c Ñ\86а Ð³Ñ\83Ñ\88.",
+       "uploadtext": "Лелайе хӀара агӀо сервер чу файлаш йохуш.\nХьалхо чуяьхна файлаш хьажа,  [[Special:FileList|кхузахь]]. Кхин чуяьхна файлаш дӀаязло [[Special:Log/upload|чуяхаран тептар чохь]], дӀаяьхна файлаш каро йиш ю [[Special:Log/delete|кхузахь]].\n\nФайл агӀона чуйилла лелабе лахара могӀанаш:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code>''' файла Файлан юьззина верси чуйиллуш;\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|цунахь лаьцна хаам]]</nowiki></code>''' 200 пиксель барамехь файл чуйилар бухахь цунахь лаьцна могӀа а болуш;\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' файлан тӀе хьажорг хӀотайо файл агӀонгахь ца гуш.",
        "upload-permitted": "Магийна файлийн тайпанаш: $1.",
        "upload-preferred": "Магийна файлийн тайпанаш: $1.",
        "upload-prohibited": "Магийна доцу файлийн тайпанаш: $1.",
        "fewestrevisions": "ЧӀогӀа кӀезиг версеш йолу агӀонаш",
        "nbytes": "$1 {{PLURAL:$1|байт}}",
        "ncategories": "$1 {{PLURAL:$1|категори|категореш}}",
-       "ninterwikis": "$1 {{PLURAL:$1|1=Ñ\8eкÑ\8aаÑ\80вики-Ñ\85Ñ\8cажоÑ\80аг|Ñ\8eкÑ\8aаÑ\80вики-Ñ\85Ñ\8cажоÑ\80гаÑ\88}}",
+       "ninterwikis": "$1 {{PLURAL:$1|1=юкъарвики-хьажорг|юкъарвики-хьажоргаш}}",
        "nlinks": "$1 {{PLURAL:$1|хьажорг}}",
        "nmembers": "$1 {{PLURAL:$1|хӀума|хӀумнаш}}",
        "nmemberschanged": "$1 → $2 {{PLURAL:$2|хӀума|хӀумнаш}}",
        "ancientpages": "ТӀехьара терахьца тадар дина яззамаш",
        "move": "ЦӀе хийца",
        "movethispage": "ХӀокху агӀон цӀе хийца",
-       "unusedimagestext": "Ð\94еÑ\85аÑ\80 Ð´Ð¾, Ñ\82идаме Ñ\8dÑ\86а, ÐºÑ\85ин Ð¹Ð¾Ð»Ñ\83 Ð´Ñ\83Ñ\8cнана Ð¼Ð°Ñ\88ан-меÑ\82Ñ\82игаÑ\88 Ð° Ð»ÐµÐ»Ð¾Ñ\88 Ñ\85ила Ð¼ÐµÐ³Ð° Ð½Ð¸Ð¹Ñ\81Ñ\81а Ð¹Ð¾Ð³Ó\80Ñ\83 Ñ\85Ñ\8cажоÑ\80аг (URL) Ñ\85Ó\80окÑ\85Ñ\83 Ñ\85Ó\80Ñ\83ман, Ñ\85Ó\80окÑ\85Ñ\83 Ð¼Ð¾Ð³Ó\80аме Ð¹Ð¾Ð³Ó\80Ñ\83Ñ\88 Ñ\8fлаÑ\85Ñ\8c Ñ\8fÑ\86аÑ\85Ñ\8c Ð° Ð¸Ð·Ð° Ñ\85ила Ð¼ÐµÐ³Ð° Ð¶Ð¸Ð³Ð°Ñ\80а Ð»ÐµÐ»Ð¾Ñ\88.",
+       "unusedimagestext": "Дехар до, тидаме эца, кхин йолу дуьнана машан-меттигаш а лелош хила мега нийсса йогӀу хьажорг (URL) хӀокху хӀуман, хӀокху могӀаме йогӀуш ялахь яцахь а иза хила мега жигара лелош.",
        "unusedcategoriestext": "ХӀокху категорешан чохь агӀонаш я кхин категореш яц.",
        "notargettitle": "Ӏалашо билгал йина яц",
        "notargettext": "И кхочушдан ахьа билгал йина яц Ӏалашонан агӀо я декъашхо.",
        "deletedcontributions": "Декъашхочун дӀабяккхина къинхьегам",
        "deletedcontributions-title": "ДӀабаьккхина къинхьегам",
        "sp-deletedcontributions-contribs": "къинхьегам",
-       "linksearch": "Ð\90Ñ\80аÑ\85Ñ\8cаÑ\80а Ñ\85Ñ\8cажоÑ\80аг",
+       "linksearch": "Арахьара хьажорг",
        "linksearch-pat": "Лехарна кеп:",
        "linksearch-ns": "ЦӀерийн ана:",
        "linksearch-ok": "Лаха",
        "linksearch-text": "Лело мега хӀоттош йолу символаш, масала, <code>*.wikipedia.org</code>.\nЛакхара даржан домен мукъа хила еза , масала<code>*.org</code><br />\nЛовш йолу {{PLURAL:$2|1=протокол|протоколаш}}: <code>$1</code> (Iад йитарца http://, протокол бакъалла язъен яцахь).",
-       "linksearch-line": "$2 â\80\94 Ñ\85Ñ\8cажоÑ\80аг ÐºÑ\85Ñ\83 $1",
+       "linksearch-line": "$2 — хьажорг кху $1",
        "listusersfrom": "Гучé баха декъашхой, болалуш болу тӀера:",
        "listusers-submit": "Гайта",
        "listusers-noresult": "Декъашхой цакарий.",
        "nolinkshere-ns": "Хаьржинчу анахь яц '''[[:$1]]''' цӀе йолу агӀонаш",
        "isredirect": "агӀо-дӀасахьажорг",
        "istemplate": "юкъаялийнарш",
-       "isimage": "Файлан Ñ\85Ñ\8cажоÑ\80аг",
+       "isimage": "Файлан хьажорг",
        "whatlinkshere-prev": "{{PLURAL:$1|1=хьалхайодарг|хьалхайодарш}} $1",
        "whatlinkshere-next": "{{PLURAL:$1|тӀаьхьайогӀург|тӀаьхьайогӀурш}} $1",
        "whatlinkshere-links": "← хьажоргаш",
        "lockedbyandtime": "($1 $2 $3)",
        "move-page": "$1 — цӀе хийцар",
        "move-page-legend": "ЦӀe хийца яр",
-       "movepagetext": "Ð\91Ñ\83Ñ\85аÑ\85Ñ\8c Ð¹Ð¾Ð»Ñ\83 Ñ\84оÑ\80манÑ\86а Ð°Ð³Ó\80он Ñ\86Ó\80е Ñ\85ийÑ\86ало. Ð¦Ñ\83л Ñ\81овнаÑ\85 Ñ\86Ñ\83Ñ\8cна Ñ\85ийÑ\86аман Ñ\82епÑ\82аÑ\80 ÐºÑ\85оÑ\8cÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82е Ð´Ð¾ÐºÐºÑ\85а. Ð¥Ñ\8cалÑ\85алеÑ\80а Ñ\86Ó\80аÑ\80аÑ\85Ñ\8c Ñ\85иÑ\80Ñ\8aÑ\8e ÐºÐµÑ\80ла ÐºÑ\85оÑ\8cллина Ð°Ð³Ó\80онан Ñ\85Ñ\8cажоÑ\80аг.\n\nÐ¥Ñ\8cовÑ\81алаÑ\88 [[Special:DoubleRedirects|Ñ\88алÑ\85а]] Ð° [[Special:BrokenRedirects|йоÑ\85на Ñ\85Ñ\8cажоÑ\80гаÑ\88]] Ñ\8eй Ñ\82еÑ\85Ñ\8c Ð°Ñ\8cлла.\n\nШÑ\83 Ð¶Ð¾Ñ\8cпеÑ\85Ñ\8c Ð´Ñ\83 Ñ\85Ñ\8cажоÑ\80гаÑ\88 Ð½Ð¸Ð¹Ñ\81а Ð½ÐµÐºÑ\8a Ð³Ð¾Ð¹Ñ\82Ñ\83Ñ\88 Ñ\85илаÑ\80ан.\n\nТидам Ð±Ðµ Ñ\85Ñ\8cалÑ\85алеÑ\80а Ð°Ð³Ó\80он Ñ\86Ó\80е â\80\98â\80\99â\80\99Ñ\85ийÑ\86алÑ\83Ñ\80 Ñ\8fÑ\86â\80\99â\80\99â\80\99 Ð¸Ñ\88Ñ\82Ñ\82а Ñ\86Ó\80е Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80о Ð¹Ð¾Ð»Ñ\83Ñ\88 ÐµÐ»Ð°Ñ\85Ñ\8c. Ð®ÐºÑ\8aаÑ\80даккÑ\85аÑ\80: Ð¹Ð¾Ð»Ñ\83Ñ\88 Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80о ÐºÑ\85оÑ\8cÑ\87Ñ\83Ñ\85Ñ\8cа Ñ\85Ñ\8cажоÑ\80аг ÐµÐ»Ð°Ñ\85Ñ\8c, Ñ\8f ÐµÑ\81а ÐµÐ»Ð°Ñ\85Ñ\8c Ð°, Ñ\86Ñ\83Ñ\8cна Ñ\85ийÑ\86аме Ð¸Ñ\81Ñ\82оÑ\80и Ñ\8fÑ\86аÑ\85Ñ\8c Ð°.\n\nÐ\98 Ð±Ð¾Ñ\85Ñ\83Ñ\80г Ð´Ñ\83 Ñ\88Ñ\83н Ð°Ð³Ó\80онан Ñ\86Ó\80е Ñ\8eÑ\85а Ð° Ñ\85Ñ\8cалÑ\85а Ñ\85иллаÑ\80гÑ\87Ñ\83нтӀе хийца йиш ю, амма йолуш йолу агӀо дӀаяккха йиш яц.\n\n'''ДӀАХЬЕДАР!'''\n\nЦӀе хийцар бахьнехь гӀаръяьлла агӀонашна дукха дагахь боцу хийцамаш хила тарло. Цундела цӀе хийцале шеш хила тарлучу тӀехьонашах кхета аьлла тешна хила.",
-       "movepagetext-noredirectfixer": "Ð\91Ñ\83Ñ\85аÑ\85Ñ\8c Ð¹Ð¾Ð»Ñ\83 Ñ\84оÑ\80манÑ\86а Ð°Ð³Ó\80он Ñ\86Ó\80е Ñ\85ийÑ\86ало. Ð¦Ñ\83л Ñ\81овнаÑ\85 Ñ\86Ñ\83Ñ\8cна Ñ\85ийÑ\86аман Ñ\82епÑ\82аÑ\80 ÐºÑ\85оÑ\8cÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82е Ð´Ð¾ÐºÐºÑ\85а. Ð¥Ñ\8cалÑ\85алеÑ\80а Ñ\86Ó\80аÑ\80аÑ\85Ñ\8c Ñ\85иÑ\80Ñ\8aÑ\8e ÐºÐµÑ\80ла ÐºÑ\85оÑ\8cллина Ð°Ð³Ó\80онан Ñ\85Ñ\8cажоÑ\80аг.\n\nÐ¥Ñ\8cовÑ\81алаÑ\88 [[Special:DoubleRedirects|Ñ\88алÑ\85а]] Ð° [[Special:BrokenRedirects|йоÑ\85на Ñ\85Ñ\8cажоÑ\80гаÑ\88]] Ñ\8eй Ñ\82еÑ\85Ñ\8c Ð°Ñ\8cлла.\n\nШÑ\83 Ð¶Ð¾Ñ\8cпеÑ\85Ñ\8c Ð´Ñ\83 Ñ\85Ñ\8cажоÑ\80гаÑ\88 Ð½Ð¸Ð¹Ñ\81а Ð½ÐµÐºÑ\8a Ð³Ð¾Ð¹Ñ\82Ñ\83Ñ\88 Ñ\85илаÑ\80ан.\n\nТидам Ð±Ðµ Ñ\85Ñ\8cалÑ\85алеÑ\80а Ð°Ð³Ó\80он Ñ\86Ó\80е â\80\98â\80\99â\80\99Ñ\85ийÑ\86алÑ\83Ñ\80 Ñ\8fÑ\86â\80\99â\80\99â\80\99 Ð¸Ñ\88Ñ\82Ñ\82а Ñ\86Ó\80е Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80о Ð¹Ð¾Ð»Ñ\83Ñ\88 ÐµÐ»Ð°Ñ\85Ñ\8c. Ð®ÐºÑ\8aаÑ\80даккÑ\85аÑ\80: Ð¹Ð¾Ð»Ñ\83Ñ\88 Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80о ÐºÑ\85оÑ\8cÑ\87Ñ\83Ñ\85Ñ\8cа Ñ\85Ñ\8cажоÑ\80аг ÐµÐ»Ð°Ñ\85Ñ\8c, Ñ\8f ÐµÑ\81а ÐµÐ»Ð°Ñ\85Ñ\8c Ð°, Ñ\86Ñ\83Ñ\8cна Ñ\85ийÑ\86аме Ð¸Ñ\81Ñ\82оÑ\80и Ñ\8fÑ\86аÑ\85Ñ\8c Ð°.\n\nÐ\98 Ð±Ð¾Ñ\85Ñ\83Ñ\80г Ð´Ñ\83 Ñ\88Ñ\83н Ð°Ð³Ó\80онан Ñ\86Ó\80е Ñ\8eÑ\85а Ð° Ñ\85Ñ\8cалÑ\85а Ñ\85иллаÑ\80гÑ\87Ñ\83нтӀе хийца йиш ю, амма йолуш йолу агӀо дӀаяккха йиш яц.\n\n'''ДӀАХЬЕДАР!'''\n\nЦӀе хийцар бахьнехь гӀаръяьлла агӀонашна дукха дагахь боцу хийцамаш хила тарло. Цундела цӀе хийцале шеш хила тарлучу тӀехьонашах кхета аьлла тешна хила.",
+       "movepagetext": "Ð\91Ñ\83Ñ\85аÑ\85Ñ\8c Ð¹Ð¾Ð»Ñ\83 Ñ\84оÑ\80манÑ\86а Ð°Ð³Ó\80он Ñ\86Ó\80е Ñ\85ийÑ\86ало. Ð¦Ñ\83л Ñ\81овнаÑ\85 Ñ\86Ñ\83Ñ\8cна Ñ\85ийÑ\86аман Ñ\82епÑ\82аÑ\80 ÐºÑ\85оÑ\8cÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82е Ð´Ð¾ÐºÐºÑ\85а. Ð¥Ñ\8cалÑ\85алеÑ\80а Ñ\86Ó\80аÑ\80аÑ\85Ñ\8c Ñ\85иÑ\80Ñ\8aÑ\8e ÐºÐµÑ\80ла ÐºÑ\85оÑ\8cллина Ð°Ð³Ó\80онан Ñ\85Ñ\8cажоÑ\80г.\n\nÐ¥Ñ\8cовÑ\81алаÑ\88 [[Special:DoubleRedirects|Ñ\88алÑ\85а]] Ð° [[Special:BrokenRedirects|йоÑ\85на Ñ\85Ñ\8cажоÑ\80гаÑ\88]] Ñ\8eй Ñ\82еÑ\85Ñ\8c Ð°Ñ\8cлла.\n\nШÑ\83 Ð¶Ð¾Ñ\8cпеÑ\85Ñ\8c Ð´Ñ\83 Ñ\85Ñ\8cажоÑ\80гаÑ\88 Ð½Ð¸Ð¹Ñ\81а Ð½ÐµÐºÑ\8a Ð³Ð¾Ð¹Ñ\82Ñ\83Ñ\88 Ñ\85илаÑ\80ан.\n\nТидам Ð±Ðµ Ñ\85Ñ\8cалÑ\85алеÑ\80а Ð°Ð³Ó\80он Ñ\86Ó\80е â\80\98â\80\99â\80\99Ñ\85ийÑ\86алÑ\83Ñ\80 Ñ\8fÑ\86â\80\99â\80\99â\80\99 Ð¸Ñ\88Ñ\82Ñ\82а Ñ\86Ó\80е Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80о Ð¹Ð¾Ð»Ñ\83Ñ\88 ÐµÐ»Ð°Ñ\85Ñ\8c. Ð®ÐºÑ\8aаÑ\80даккÑ\85аÑ\80: Ð¹Ð¾Ð»Ñ\83Ñ\88 Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80о ÐºÑ\85оÑ\8cÑ\87Ñ\83Ñ\85Ñ\8cа Ñ\85Ñ\8cажоÑ\80г ÐµÐ»Ð°Ñ\85Ñ\8c, Ñ\8f ÐµÑ\81а ÐµÐ»Ð°Ñ\85Ñ\8c Ð°, Ñ\86Ñ\83Ñ\8cна Ñ\85ийÑ\86аме Ð¸Ñ\81Ñ\82оÑ\80и Ñ\8fÑ\86аÑ\85Ñ\8c Ð°.\n\nÐ\98 Ð±Ð¾Ñ\85Ñ\83Ñ\80г Ð´Ñ\83 Ñ\88Ñ\83н Ð°Ð³Ó\80онан Ñ\86Ó\80е Ñ\8eÑ\85а Ð° Ñ\85Ñ\8cалÑ\85а Ñ\85иллаÑ\87Ñ\83н тӀе хийца йиш ю, амма йолуш йолу агӀо дӀаяккха йиш яц.\n\n'''ДӀАХЬЕДАР!'''\n\nЦӀе хийцар бахьнехь гӀаръяьлла агӀонашна дукха дагахь боцу хийцамаш хила тарло. Цундела цӀе хийцале шеш хила тарлучу тӀехьонашах кхета аьлла тешна хила.",
+       "movepagetext-noredirectfixer": "Ð\91Ñ\83Ñ\85аÑ\85Ñ\8c Ð¹Ð¾Ð»Ñ\83 Ñ\84оÑ\80манÑ\86а Ð°Ð³Ó\80он Ñ\86Ó\80е Ñ\85ийÑ\86ало. Ð¦Ñ\83л Ñ\81овнаÑ\85 Ñ\86Ñ\83Ñ\8cна Ñ\85ийÑ\86аман Ñ\82епÑ\82аÑ\80 ÐºÑ\85оÑ\8cÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82е Ð´Ð¾ÐºÐºÑ\85а. Ð¥Ñ\8cалÑ\85алеÑ\80а Ñ\86Ó\80аÑ\80аÑ\85Ñ\8c Ñ\85иÑ\80Ñ\8aÑ\8e ÐºÐµÑ\80ла ÐºÑ\85оÑ\8cллина Ð°Ð³Ó\80онан Ñ\85Ñ\8cажоÑ\80г.\n\nÐ¥Ñ\8cовÑ\81алаÑ\88 [[Special:DoubleRedirects|Ñ\88алÑ\85а]] Ð° [[Special:BrokenRedirects|йоÑ\85на Ñ\85Ñ\8cажоÑ\80гаÑ\88]] Ñ\8eй Ñ\82еÑ\85Ñ\8c Ð°Ñ\8cлла.\n\nШÑ\83 Ð¶Ð¾Ñ\8cпеÑ\85Ñ\8c Ð´Ñ\83 Ñ\85Ñ\8cажоÑ\80гаÑ\88 Ð½Ð¸Ð¹Ñ\81а Ð½ÐµÐºÑ\8a Ð³Ð¾Ð¹Ñ\82Ñ\83Ñ\88 Ñ\85илаÑ\80ан.\n\nТидам Ð±Ðµ Ñ\85Ñ\8cалÑ\85алеÑ\80а Ð°Ð³Ó\80он Ñ\86Ó\80е â\80\98â\80\99â\80\99Ñ\85ийÑ\86алÑ\83Ñ\80 Ñ\8fÑ\86â\80\99â\80\99â\80\99 Ð¸Ñ\88Ñ\82Ñ\82а Ñ\86Ó\80е Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80о Ð¹Ð¾Ð»Ñ\83Ñ\88 ÐµÐ»Ð°Ñ\85Ñ\8c. Ð®ÐºÑ\8aаÑ\80даккÑ\85аÑ\80: Ð¹Ð¾Ð»Ñ\83Ñ\88 Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80о ÐºÑ\85оÑ\8cÑ\87Ñ\83Ñ\85Ñ\8cа Ñ\85Ñ\8cажоÑ\80г ÐµÐ»Ð°Ñ\85Ñ\8c, Ñ\8f ÐµÑ\81а ÐµÐ»Ð°Ñ\85Ñ\8c Ð°, Ñ\86Ñ\83Ñ\8cна Ñ\85ийÑ\86аме Ð¸Ñ\81Ñ\82оÑ\80и Ñ\8fÑ\86аÑ\85Ñ\8c Ð°.\n\nÐ\98 Ð±Ð¾Ñ\85Ñ\83Ñ\80г Ð´Ñ\83 Ñ\88Ñ\83н Ð°Ð³Ó\80онан Ñ\86Ó\80е Ñ\8eÑ\85а Ð° Ñ\85Ñ\8cалÑ\85а Ñ\85иллаÑ\87Ñ\83н тӀе хийца йиш ю, амма йолуш йолу агӀо дӀаяккха йиш яц.\n\n'''ДӀАХЬЕДАР!'''\n\nЦӀе хийцар бахьнехь гӀаръяьлла агӀонашна дукха дагахь боцу хийцамаш хила тарло. Цундела цӀе хийцале шеш хила тарлучу тӀехьонашах кхета аьлла тешна хила.",
        "movepagetalktext": "ТӀе хӀоьттина йолу дийцаре агӀо ишта цӀе хийцина хира ю, '''цхьа йолу ханчохь, маца:'''\n\n*Йаьсса йоцу дийцаре агӀо йолуш ю оцу цӀарца йа\n*Ахьа къастаман харжам цабиняхь а къастам хӀотточехь.\n\nИшта чу ханчохь, ахьа дехьа яккха йезар ю йа куьйга хӀоттайар, нагахь иза хьашт йалахь.",
        "movearticle": "ЦӀе хийца агӀон",
        "moveuserpage-warning": "'''Тергам бе.''' Хьо декъашхочун агӀона цӀе хийца гӀерта. Дехар до, тергам бе, декъашхочун агӀона цӀе бен хийца лур яц, декъашхочун дӀаяздаран цӀе хийца лур яц.",
        "protectedpagemovewarning": "'''ДӀахьедар.''' ХӀара агӀо гӀаролла йина ю; цӀе хийца я нисйа а бакъо йолуш куьйгалхой бе бац.\nЛахахьа тептаро балийна тӀаьхьаралера дӀаязбина хаам:",
        "semiprotectedpagemovewarning": "'''ДӀахьедо.''' ХӀара агӀо гӀаролла йина ю; дӀабазбиначу декъашхошка бе цӀе хийцалуш яц.\nЛахахьа тептаро балийна тӀаьхьаралера дӀаязбина хаам:",
        "export": "АгӀонаш араяхар",
-       "exporttext": "ШÑ\83Ñ\8cга Ð´Ð°Ð»Ñ\83Ñ\80 Ð´Ñ\83 ÐºÑ\85еÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82еÑ\80а Ñ\87Ñ\83даÑ\85аÑ\80Ñ\88, Ð¹Ð¾Ð·Ð° Ð° Ñ\85ийÑ\86аме Ñ\82епÑ\82аÑ\80Ñ\88 Ð±Ð¸Ð»Ð³Ð°Ð»Ð»Ð° Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80онаÑ\88 Ð¹Ð° Ð³Ñ\83лдина Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80онаÑ\88 Ñ\85Ó\80окÑ\85 XML Ð±Ð°Ñ\80амÑ\86а, Ñ\8eÑ\85а Ñ\82Ó\80Ñ\8fÑ\85Ñ\8cа Ñ\87Ñ\83Ñ\80а [[Special:Import|Ñ\85Ñ\8cаÑ\8dÑ\86алÑ\83Ñ\80долÑ\88]] ÐºÑ\85еÑ\87Ñ\83 Ð²Ð¸ÐºÐ¸-Ñ\85Ñ\8cалÑ\85ен, Ð±Ð¾Ð»Ñ\85 Ð±ÐµÑ\88 Ð¹Ð¾Ð»Ñ\83 Ñ\85lокÑ\85Ñ\83 MediaWiki Ð³lиÑ\80Ñ\81аÑ\86а.\n\nÐ\9aÑ\85еÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82еÑ\80а Ñ\8fззамаÑ\88 Ñ\87Ñ\83йаÑ\85а, Ñ\87Ñ\83Ñ\8fзйе Ñ\86Ó\80е Ñ\82адеÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82е, Ñ\86Ó\80Ñ\85Ñ\8cа Ð¼Ð¾Ð³Ó\80ан Ñ\86Ó\80е Ð¼Ð¾Ð³Ó\80аÑ\80Ñ\88каÑ\85Ñ\8c, Ñ\8eÑ\85а Ñ\85аÑ\80жа Ð»Ð°Ñ\8cи Ñ\88Ñ\83на Ð\9aÑ\85еÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82еÑ\80 Ñ\87Ñ\83йаÑ\85а Ð¼Ð°Ñ\81Ñ\81о Ñ\8fззамаÑ\88на Ð¸Ñ\81Ñ\82оÑ\80и Ñ\85ийÑ\86амбаÑ\80Ñ\88 Ð¹Ð° Ñ\82Ó\80Ñ\8fÑ\85Ñ\8cаÑ\80алеÑ\80а Ñ\8fззамна Ð±Ð°Ñ\88Ñ\85о.\n\nШÑ\83Ñ\8cга ÐºÑ\85и Ð´Ð°Ð»Ð°Ð½Ð´ÐµÑ\80г, Ð»ÐµÐ»Ð°ÐµÑ\88 Ð¹Ð¾Ð»Ñ\83 Ð¼ÐµÑ\82Ñ\82иг ÐºÑ\8aаÑ\81Ñ\82аман Ð¼Ð°Ñ\88ан Ñ\85Ñ\8cажоÑ\80аг ÐºÑ\85еÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82еÑ\80 Ñ\87Ñ\83даÑ\85а Ñ\82Ó\80аÑ\8cÑ\85Ñ\8cаÑ\80леÑ\80аÑ\87Ñ\83 Ð±Ð°Ñ\88Ñ\85он Ñ\8fззамаÑ\88. Ð\9cаÑ\81ала Ð¾Ñ\86Ñ\83 Ñ\8fззамна [[{{MediaWiki:Mainpage}}]] Ñ\85Ó\80аÑ\80а Ñ\85иÑ\80а Ñ\8e Ñ\85Ñ\8cажоÑ\80аг [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]].",
+       "exporttext": "ШÑ\83Ñ\8cга Ð´Ð°Ð»Ñ\83Ñ\80 Ð´Ñ\83 ÐºÑ\85еÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82еÑ\80а Ñ\87Ñ\83даÑ\85аÑ\80Ñ\88, Ð¹Ð¾Ð·Ð° Ð° Ñ\85ийÑ\86аме Ñ\82епÑ\82аÑ\80Ñ\88 Ð±Ð¸Ð»Ð³Ð°Ð»Ð»Ð° Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80онаÑ\88 Ð¹Ð° Ð³Ñ\83лдина Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80онаÑ\88 Ñ\85Ó\80окÑ\85 XML Ð±Ð°Ñ\80амÑ\86а, Ñ\8eÑ\85а Ñ\82Ó\80Ñ\8fÑ\85Ñ\8cа Ñ\87Ñ\83Ñ\80а [[Special:Import|Ñ\85Ñ\8cаÑ\8dÑ\86алÑ\83Ñ\80долÑ\88]] ÐºÑ\85еÑ\87Ñ\83 Ð²Ð¸ÐºÐ¸-Ñ\85Ñ\8cалÑ\85ен, Ð±Ð¾Ð»Ñ\85 Ð±ÐµÑ\88 Ð¹Ð¾Ð»Ñ\83 Ñ\85lокÑ\85Ñ\83 MediaWiki Ð³lиÑ\80Ñ\81аÑ\86а.\n\nÐ\9aÑ\85еÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82еÑ\80а Ñ\8fззамаÑ\88 Ñ\87Ñ\83йаÑ\85а, Ñ\87Ñ\83Ñ\8fзйе Ñ\86Ó\80е Ñ\82адеÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82е, Ñ\86Ó\80Ñ\85Ñ\8cа Ð¼Ð¾Ð³Ó\80ан Ñ\86Ó\80е Ð¼Ð¾Ð³Ó\80аÑ\80Ñ\88каÑ\85Ñ\8c, Ñ\8eÑ\85а Ñ\85аÑ\80жа Ð»Ð°Ñ\8cи Ñ\88Ñ\83на Ð\9aÑ\85еÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82еÑ\80 Ñ\87Ñ\83йаÑ\85а Ð¼Ð°Ñ\81Ñ\81о Ñ\8fззамаÑ\88на Ð¸Ñ\81Ñ\82оÑ\80и Ñ\85ийÑ\86амбаÑ\80Ñ\88 Ð¹Ð° Ñ\82Ó\80Ñ\8fÑ\85Ñ\8cаÑ\80алеÑ\80а Ñ\8fззамна Ð±Ð°Ñ\88Ñ\85о.\n\nШÑ\83Ñ\8cга ÐºÑ\85и Ð´Ð°Ð»Ð°Ð½Ð´ÐµÑ\80г, Ð»ÐµÐ»Ð°ÐµÑ\88 Ð¹Ð¾Ð»Ñ\83 Ð¼ÐµÑ\82Ñ\82иг ÐºÑ\8aаÑ\81Ñ\82аман Ð¼Ð°Ñ\88ан Ñ\85Ñ\8cажоÑ\80г ÐºÑ\85еÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82еÑ\80 Ñ\87Ñ\83даÑ\85а Ñ\82Ó\80аÑ\8cÑ\85Ñ\8cаÑ\80леÑ\80аÑ\87Ñ\83 Ð±Ð°Ñ\88Ñ\85он Ñ\8fззамаÑ\88. Ð\9cаÑ\81ала Ð¾Ñ\86Ñ\83 Ñ\8fззамна [[{{MediaWiki:Mainpage}}]] Ñ\85Ó\80аÑ\80а Ñ\85иÑ\80а Ñ\8e Ñ\85Ñ\8cажоÑ\80г [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]].",
        "exportall": "Массо агӀонаш экспорт ян",
        "exportcuronly": "Карара верси бен юкъа ма тоха, юзийна хьалхалерра истори йоцуш",
        "export-submit": "Экспорт ян",
        "tooltip-t-upload": "Чуйаха файлаш",
        "tooltip-t-specialpages": "Белха агӀонанийн могӀам",
        "tooltip-t-print": "Хlокху агlонна зорба туху башхо",
-       "tooltip-t-permalink": "Ð\94аима Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cажоÑ\80аг Ñ\85Ó\80окÑ\85Ñ\83 Ð±Ð°Ñ\88Ñ\85а Ð°Ð³Ó\80онна",
+       "tooltip-t-permalink": "Даима йолу хьажорг хӀокху башха агӀонна",
        "tooltip-ca-nstab-main": "Яззамна чулацам",
        "tooltip-ca-nstab-user": "ХӀора декъашхочун долахь йолу агӀо ю",
        "tooltip-ca-nstab-media": "Медиа-файл",
        "creditspage": "Баркаллаш",
        "nocredits": "Бац декъашхойн могӀам хӀокху яззамца",
        "spamprotectiontitle": "Совбиларна литтар",
-       "spamprotectiontext": "Ð¥Ñ\8cо Ð´Ó\80аÑ\8fзÑ\8aÑ\8fн Ð³Ó\80еÑ\80Ñ\82а Ð°Ð³Ó\80о Ñ\81пам-лиÑ\82Ñ\82аÑ\80о Ð´Ó\80акÑ\8aоÑ\8cвлина.\nЦÑ\83на Ð±Ð°Ñ\85Ñ\8cна Ñ\85ила Ñ\82ам Ð±Ñ\83 Ð°Ð³Ó\80она Ñ\87оÑ\85Ñ\8c Ð·Ñ\83лам Ð»Ð¸Ñ\82Ñ\82аÑ\80ан Ñ\87Ñ\83Ñ\82оÑ\8cÑ\85на Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cажоÑ\80аг Ñ\85илаÑ\80.",
+       "spamprotectiontext": "Хьо дӀаязъян гӀерта агӀо спам-литтаро дӀакъоьвлина.\nЦуна бахьна хила там бу агӀона чохь зулам литтаран чутоьхна йолу хьажорг хилар.",
        "spambot_username": "Спам дӀацӀаняр",
        "pageinfo-title": "Хаамаш цу «$1»",
        "pageinfo-not-current": "Шира версийн оьцу хааме хьажа таро яц.",
        "saturday-at": "шот дийнахь $1",
        "sunday-at": "кӀиранан дийнахь $1",
        "yesterday-at": "селхана $1 даьлча",
-       "bad_image_list": "Ð\91аÑ\80ам Ñ\85ила Ð±ÐµÐ·Ð° Ð¸Ñ\88Ñ\82а:\n\nÐ\9bоÑ\80аÑ\88 Ñ\85иÑ\80а Ñ\8e Ð¼Ð¾Ð³Ó\80амÑ\8fÑ\85Ñ\8c Ð¹Ð¾Ð»Ñ\83 Ñ\85Ó\80Ñ\83мнаÑ\88 (могÓ\80ийн, Ð¹Ð¾Ð»Ð° Ð»Ñ\83Ñ\88 Ð¹Ð¾Ð»Ñ\83 Ñ\81имвол Ñ\82Ó\80иÑ\80а *).\nÐ\94Ñ\83Ñ\8cÑ\85Ñ\85Ñ\8cаÑ\80алеÑ\80а Ñ\85Ñ\8cажоÑ\80аг Ð¼Ð°Ð³Ó\80аÑ\80Ñ\88и Ñ\85ила Ð±ÐµÐ·Ð° Ñ\85Ñ\8cажоÑ\80аг ÐºÑ\85Ñ\83 Ñ\86амагдо Ñ\81Ñ\83Ñ\80Ñ\82 Ð´Ñ\83Ñ\8cлаÑ\87е.\nТÓ\80Ñ\8fÑ\85Ñ\8cа Ð¹Ð¾Ð³Ó\80Ñ\83Ñ\88 Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cажоÑ\80аг оцу могӀарехь хира ю магóш, билгалла аьлча яззамаш долуче, сурт хьаллаточехь.",
+       "bad_image_list": "Ð\91аÑ\80ам Ñ\85ила Ð±ÐµÐ·Ð° Ð¸Ñ\88Ñ\82а:\n\nÐ\9bоÑ\80аÑ\88 Ñ\85иÑ\80а Ñ\8e Ð¼Ð¾Ð³Ó\80амÑ\8fÑ\85Ñ\8c Ð¹Ð¾Ð»Ñ\83 Ñ\85Ó\80Ñ\83мнаÑ\88 (могÓ\80ийн, Ð¹Ð¾Ð»Ð° Ð»Ñ\83Ñ\88 Ð¹Ð¾Ð»Ñ\83 Ñ\81имвол Ñ\82Ó\80иÑ\80а *).\nÐ\94Ñ\83Ñ\8cÑ\85Ñ\85Ñ\8cаÑ\80алеÑ\80а Ñ\85Ñ\8cажоÑ\80г Ð¼Ð°Ð³Ó\80анийн Ñ\85ила Ð±ÐµÐ·Ð° Ñ\85Ñ\8cажоÑ\80г ÐºÑ\85Ñ\83 Ñ\86амагдо Ñ\81Ñ\83Ñ\80Ñ\82 Ð´Ñ\83Ñ\8cлаÑ\87е.\nТÓ\80Ñ\8fÑ\85Ñ\8cа Ð¹Ð¾Ð³Ó\80Ñ\83Ñ\88 Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cажоÑ\80г оцу могӀарехь хира ю магóш, билгалла аьлча яззамаш долуче, сурт хьаллаточехь.",
        "metadata": "Метахаамаш",
        "metadata-help": "ХӀокху файлаца кхин тӀе хаам бу, даиман чуйоккхуш йолу терахьца чоьнашца йа тӀейоккхучуьнца. Нагахь файлан тӀаьхьа хийцам биняхь, тӀаккха цӀхьаболу барам цӀхьаьна ца ба мега хӀинцалера суьртаца.",
        "metadata-expand": "Гайта кхин тlе болу хаам",
index 4407ee3..7df6b42 100644 (file)
@@ -53,7 +53,7 @@
        "tog-shownumberswatching": "Zobrazovat počet sledujících uživatelů",
        "tog-oldsig": "Stávající podpis:",
        "tog-fancysig": "Používat v podpisu wikitext (bez automatického odkazu)",
-       "tog-uselivepreview": "Používat rychlý náhled (experimentální)",
+       "tog-uselivepreview": "Používat rychlý náhled",
        "tog-forceeditsummary": "Upozornit, když nevyplním shrnutí editace",
        "tog-watchlisthideown": "Na seznamu sledovaných stránek skrýt moje editace",
        "tog-watchlisthidebots": "Na seznamu sledovaných stránek skrýt editace botů",
        "anoneditwarning": "'''Varování:''' Nejste přihlášen(a). Pokud uložíte jakoukoli editaci, bude vaše IP adresa zveřejněna v historii této stránky. Pokud se <strong>[$1 přihlásíte]</strong> nebo si <strong>[$2 vytvoříte účet]</strong>, budou vaše editace připsány vašemu uživatelskému jménu a získáte i další výhody.",
        "anonpreviewwarning": "''Nejste přihlášen(a). Uložením zveřejníte svou IP adresu v historii této stránky.''",
        "missingsummary": "'''Připomenutí:''' Nezadali jste shrnutí editace. Pokud ještě jednou kliknete na Uložit změny, bude vaše editace zapsána bez shrnutí.",
+       "selfredirect": "<strong>Upozornění:</strong> Vytváříte přesměrování na týž článek. Pokud ještě jednou kliknete na „{{int:savearticle}}“, bude přesměrování vytvořeno.",
        "missingcommenttext": "Zadejte komentář",
        "missingcommentheader": "'''Připomenutí:''' Nezadali jste předmět/nadpis pro tento komentář.\nPokud ještě jednou kliknete na „{{int:savearticle}}“, bude vaše editace zapsána i bez toho.",
        "summary-preview": "Náhled shrnutí:",
        "log-name-pagelang": "Kniha změn jazyků",
        "log-description-pagelang": "Toto je protokol změn jazyků stránek.",
        "logentry-pagelang-pagelang": "$1 {{GENDER:$2|změnil|změnila}} jazyk stránky $3 z $4 na $5.",
-       "default-skin-not-found": "Jejda! Výchozí vzhled vaší wiki, definovaný ve <code dir=\"ltr\">$wgDefaultSkin</code> jako <code>$1</code>, není dostupný.\n\nVaše instalace zřejmě obsahuje následující vzhledy. Informace o tom, jak je povolit a vybrat výchozí, najdete na stránce [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Skin_configuration/cs Manual:Skin configuration].\n\n$2\n\n; Pokud jste právě nainstalovali MediaWiki:\n: Zřejmě jste instalovali z gitu nebo nějakým jiným způsobem přímo ze zdrojového kódu. Tak to má fungovat. Zkuste nainstalovat některé vzhledy ze [https://www.mediawiki.org/wiki/Category:All_skins seznamu vzhledů na mediawiki.org] buď:\n:* Můžete si stáhnout [https://www.mediawiki.org/wiki/Download/cs instalace v tarballu], která zahrnuje několik vzhledů a rozšíření, a vykopírovat si z ní adresář <code dir=\"ltr\">skins/</code>, nebo\n:* Nebo si můžete gitem naklonovat jeden z repozitářů <code>mediawiki/skins/*</code> do adresáře <code>skins/</code> ve vaší instalaci MediaWiki.\n: Pokud jste vývojářem MediaWiki, nemělo by to nijak narušit váš gitový repozitář.\n\n; Pokud jste právě aktualizovali MediaWiki:\n: MediaWiki 1.24 a novější již automaticky nepovolují nainstalované vzhledy (vizte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Skin_autodiscovery/cs Manual:Skin autodiscovery]). Pro povolení všech právě nainstalovaných vzhledů vlepte následující řádky do <code>LocalSettings.php</code>:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Pokud jste právě upravili <code>LocalSettings.php</code>:\n: Překontrolujte případné překlepy v názvech vzhledů.",
-       "default-skin-not-found-no-skins": "Jejda! Výchozí vzhled vaší wiki, definovaný ve <code dir=\"ltr\">$wgDefaultSkin</code> jako <code>$1</code>, není dostupný.\n\nNemáte nainstalovány žádné vzhledy.\n\n; Pokud jste právě nainstalovali nebo aktualizovali MediaWiki:\n: Zřejmě jste instalovali z gitu nebo nějakým jiným způsobem přímo ze zdrojového kódu. Tak to má fungovat. MediaWiki 1.24 a novější již v hlavním repozitáři neobsahují žádné vzhledy. Zkuste nainstalovat některé vzhledy ze [https://www.mediawiki.org/wiki/Category:All_skins seznamu vzhledů na mediawiki.org] buď:\n:* Můžete si stáhnout [https://www.mediawiki.org/wiki/Download/cs instalace v tarballu], která zahrnuje několik vzhledů a rozšíření, a vykopírovat si z ní adresář <code>skins/</code>, nebo\n:* Nebo si můžete gitem naklonovat jeden z repozitářů <code>mediawiki/skins/*</code> do adresáře <code dir=\"ltr\">skins/</code> ve vaší instalaci MediaWiki.\n: Pokud jste vývojářem MediaWiki, nemělo by to nijak narušit váš gitový repozitář. Informace o tom, jak povolit vzhledy a vybrat výchozí, najdete na stránce [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Skin_configuration/cs Manual:Skin configuration].",
+       "default-skin-not-found": "Jejda! Výchozí vzhled vaší wiki, definovaný ve <code dir=\"ltr\">$wgDefaultSkin</code> jako <code>$1</code>, není dostupný.\n\nVaše instalace zřejmě obsahuje následující vzhledy. Informace o tom, jak je povolit a vybrat výchozí, najdete na stránce [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Skin_configuration/cs Manual:Skin configuration].\n\n$2\n\n; Pokud jste právě nainstalovali MediaWiki:\n: Zřejmě jste instalovali z gitu nebo nějakým jiným způsobem přímo ze zdrojového kódu. Tak to má fungovat. Zkuste nainstalovat některé vzhledy ze [https://www.mediawiki.org/wiki/Category:All_skins seznamu vzhledů na mediawiki.org] buď:\n:* Můžete si stáhnout [https://www.mediawiki.org/wiki/Download/cs instalaci v tarballu], která zahrnuje několik vzhledů a rozšíření, a vykopírovat si z ní adresář <code dir=\"ltr\">skins/</code>.\n:* Nebo si můžete stáhnout tarbally jednotlivých vzhledů z [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* Nebo si můžete gitem naklonovat jeden z repozitářů <code>mediawiki/skins/*</code> do adresáře <code>skins/</code> ve vaší instalaci MediaWiki.\n: Pokud jste vývojářem MediaWiki, nemělo by to nijak narušit váš gitový repozitář.\n\n; Pokud jste právě aktualizovali MediaWiki:\n: MediaWiki 1.24 a novější již automaticky nepovolují nainstalované vzhledy (vizte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Skin_autodiscovery/cs Manual:Skin autodiscovery]). Pro povolení všech právě nainstalovaných vzhledů vlepte následující řádky do <code>LocalSettings.php</code>:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Pokud jste právě upravili <code>LocalSettings.php</code>:\n: Překontrolujte případné překlepy v názvech vzhledů.",
+       "default-skin-not-found-no-skins": "Jejda! Výchozí vzhled vaší wiki, definovaný ve <code dir=\"ltr\">$wgDefaultSkin</code> jako <code>$1</code>, není dostupný.\n\nNemáte nainstalovány žádné vzhledy.\n\n; Pokud jste právě nainstalovali nebo aktualizovali MediaWiki:\n: Zřejmě jste instalovali z gitu nebo nějakým jiným způsobem přímo ze zdrojového kódu. Tak to má fungovat. MediaWiki 1.24 a novější již v hlavním repozitáři neobsahují žádné vzhledy. Zkuste nainstalovat některé vzhledy ze [https://www.mediawiki.org/wiki/Category:All_skins seznamu vzhledů na mediawiki.org] buď:\n:* Můžete si stáhnout [https://www.mediawiki.org/wiki/Download/cs instalaci v tarballu], která zahrnuje několik vzhledů a rozšíření, a vykopírovat si z ní adresář <code>skins/</code>.\n:* Nebo si můžete stáhnout tarbally jednotlivých vzhledů z [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* Nebo si můžete gitem naklonovat jeden z repozitářů <code>mediawiki/skins/*</code> do adresáře <code dir=\"ltr\">skins/</code> ve vaší instalaci MediaWiki.\n: Pokud jste vývojářem MediaWiki, nemělo by to nijak narušit váš gitový repozitář. Informace o tom, jak povolit vzhledy a vybrat výchozí, najdete na stránce [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Skin_configuration/cs Manual:Skin configuration].",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (povolený)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''zakázaný''')",
        "mediastatistics": "Statistika souborů",
index ebfeb6d..b0200ec 100644 (file)
        "anoneditwarning": "<strong>Warnung:</strong> Du bist nicht angemeldet. Deine IP-Adresse wird öffentlich sichtbar, falls du Bearbeitungen durchführst. Wenn du dich <strong>[$1 anmeldest]</strong> oder <strong>[$2 ein Benutzerkonto erstellst]</strong>, werden deine Bearbeitungen zusammen mit anderen Beiträgen deinem Benutzernamen zugeordnet.",
        "anonpreviewwarning": "''Du bist nicht angemeldet. Beim Speichern wird deine IP-Adresse in der Versionsgeschichte aufgezeichnet.''",
        "missingsummary": "'''Hinweis:''' Du hast keine Zusammenfassung angegeben. Wenn du erneut auf „{{int:savearticle}}“ klickst, wird deine Änderung ohne Zusammenfassung übernommen.",
+       "selfredirect": "<strong>Warnung:</strong> Du erstellst eine Weiterleitung auf den gleichen Artikel.\nWenn du erneut auf „{{int:savearticle}}“ klickst, wird die Weiterleitung erstellt.",
        "missingcommenttext": "Dein Abschnitt enthält keinen Text.",
        "missingcommentheader": "'''Achtung:''' Du hast kein Betreff/Überschrift eingegeben. Wenn du erneut auf „{{int:savearticle}}“ klickst, wird deine Bearbeitung ohne Überschrift gespeichert.",
        "summary-preview": "Vorschau der Zusammenfassungszeile:",
index 8d6f1e8..82e3fdf 100644 (file)
@@ -33,7 +33,7 @@
        "tog-shownumberswatching": "Fà vèder al nómer ed j utèint che gh'àn la pàgina sòta uservasiòun",
        "tog-oldsig": "La fîrma 'd adèsa",
        "tog-fancysig": "Trâta la fîrma cme wikitèst (sèinsa colegamèint avtomâtich)",
-       "tog-uselivepreview": "Permèt la funsiòun \"Live preview\" (guêrda préma 'd salvêr dal vîv - in sperimèint)",
+       "tog-uselivepreview": "Permèt la funsiòun \"Live preview\" (guêrda préma 'd salvêr in dirèta)",
        "tog-forceeditsummary": "Dmânda s'l'è vèira che al câmp argumèint l' é vōd",
        "tog-watchlisthideown": "Lōga al mé mudéfichi int i  tgnû 'd ôc specêl",
        "tog-watchlisthidebots": "Lōga al mudéfichi di bot int i tgnû 'd ôc specêl",
        "anoneditwarning": "<strong>Atèinti:</strong> An n'é mìa stê fât l'ingrès. S' ét farê dal mudéfichi al tó indirés IP al srà vést da tót. Se <strong>[$1 và dèinter]</strong> o <strong>[$2 fà 'n' utèinsa]</strong>, al tô mudéfichi a srân sgnêdi al tó nòm utèint, insèm a êter benefési.",
        "anonpreviewwarning": "\"An n'é mìa stê fât l'ingrès. Mèinter es sêlva la pàgina, l'indirés IP al srà sgnê int la stòria 'd la pàgina.\"",
        "missingsummary": "'''Atensiòun:''' an n'é mìa stê precişê al mutîv de sté mudéfica. S'es tōrna a clichêr insém a \"{{int:savearticle}}\" la mudéfica la gnirà salvêda cun al mutîv vōd.",
+       "selfredirect": "<strong>Ateinti:</strong>t'é drē fêr un rinvéi a l'istèsa vōş. S'ét fê cléch incòra in sém a \"{{int:savearticle}}\", al rinvéi al gnirà fât",
        "missingcommenttext": "Scréver un cumèint ché sòta.",
        "missingcommentheader": "'''Atensiòun:''' an n'é mìa stê precişê al mutîv/al tétol de sté mudéfica. S'es tōrna a clichêr insém a \"{{int:savearticle}}\" la mudéfica la gnirà salvêda sèinsa tétol.",
        "summary-preview": "Guêrda préma sûnt:",
        "right-editmyprivateinfo": "Câmbia 'l tō infurmasiòun personêli (per eşèimpi: indirés ed pôsta eletrônica, nòm vèira)",
        "right-editmyoptions": "Câmbia al tō preferèinsi",
        "right-rollback": "Scanşèla a la şvêlta al mudéfichi ed l'ûltèint ch'l'à mudifichê 'na pàgina pariculêra",
+       "right-markbotedits": "Sègna al mudéfichi da turnêr a mèter cme préma cme fâti da 'na mâchina in avtomâtich",
+       "right-noratelimit": "An n'é mìa ublighê al lémit 'd asiòun",
+       "right-import": "Côpia dal pàgini da 'd j êter wiki",
        "newuserlogpage": "Utèint nōv",
        "action-read": "lēzer cla pàgina ché",
        "action-edit": "Mudifichêr cla pàgina ché",
index 38f9981..4564aac 100644 (file)
        "specialpages": "Páginas especiales",
        "specialpages-note-top": "Leyenda",
        "specialpages-note": "* Páginas especiales normales\n* <span class=\"mw-specialpagerestricted\">Páginas especiales restringidas.</span>\n* <span class=\"mw-specialpagecached\">Páginas especiales en caché (podrían ser obsoletas).</span>",
-       "specialpages-group-maintenance": "Reportes de mantenimiento",
+       "specialpages-group-maintenance": "Informes de mantenimiento",
        "specialpages-group-other": "Otras páginas especiales",
        "specialpages-group-login": "Acceder/crear cuenta",
        "specialpages-group-changes": "Cambios recientes y registros",
index ed64d7c..79a45ea 100644 (file)
        "anoneditwarning": "<strong>Varoitus:</strong> Et ole kirjautunut sisään. IP-osoitteesi näkyy julkisesti kaikille, jos muokkaat. Jos <strong>[$1 kirjaudut sisään]</strong> tai <strong>[$2 luot tunnuksen]</strong>, muokkauksesi kirjataan käyttäjätunnuksesi tekemiksi ja samalla saat käyttöösi hyödyllisiä välineitä.",
        "anonpreviewwarning": "''Et ole kirjautunut sisään. Tallentaminen kirjaa IP-osoitteesi tämän sivun muutoshistoriaan.''",
        "missingsummary": "Et ole antanut yhteenvetoa. Jos valitset Tallenna uudelleen, niin muokkauksesi tallennetaan ilman yhteenvetoa.",
+       "selfredirect": "<strong>Varoitus:</strong> Olet tekemässä uudelleenohjausta samaan artikkeliin. Jos painat toimintoa \"{{int:savearticle}}\" uudestaan, tämä ohjaussivu luodaan.",
        "missingcommenttext": "Kirjoita viesti alle.",
        "missingcommentheader": "Et ole antanut otsikkoa kommentillesi. Napsauta ”{{int:savearticle}}”, jos et halua antaa otsikkoa.",
        "summary-preview": "Yhteenvedon esikatselu:",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
        "duplicate-args-category": "Sivut, jotka käyttävät kaksinkertaisia argumentteja mallinekutsuissa",
+       "duplicate-args-category-desc": "Tämä sivu sisältää sellaisia mallinekutsuja, jotka käyttävät kaksi kertaa samaa argumenttia kuten <nowiki>{{foo|bar=1|bar=2}}</nowiki></code> taikka <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "Tällä sivulla on liian monta hitaiden laajennusfunktioiden kutsua.\nKutsuja pitäisi olla alle $2 {{PLURAL:$2|kappale|kappaletta}}, mutta nyt niitä on $1 {{PLURAL:$1|kappale|kappaletta}}.",
        "expensive-parserfunction-category": "Sivut, joissa on liian monta vaativaa jäsenninfunktiota",
        "post-expand-template-inclusion-warning": "'''Varoitus:''' Sisällytettyjen mallineiden koko on liian suuri.\nJoitakin mallineita ei ole sisällytetty.",
        "expand_templates_generate_xml": "Näytä XML-jäsennyspuu",
        "expand_templates_generate_rawhtml": "Näytä raaka HTML",
        "expand_templates_preview": "Esikatselu",
+       "expand_templates_preview_fail_html": "<em>Koska sivustolla {{SITENAME}} on käytössä puhdas HTML-koodi ja koska istunnon tiedot ovat kadonneet, esikatselu on piilotettu JavaScript-hyökkäyksien torjumiseksi.</em>\n\n<strong>Jos olet oikealla asialla, yritä uudestaan.</strong>\nJos esikatselu ei vieläkään toimi, kokeile [[Special:UserLogout|kirjautua ulos]] ja sen jälkeen kirjaudu uudestaan sisään.",
+       "expand_templates_preview_fail_html_anon": "<em>Koska sivustolla {{SITENAME}} on käytössä puhdas HTML-koodi ja koska et ole kirjautunut sisään, esikatselu on piilotettu JavaScript-hyökkäyksien torjumiseksi.</em>\n\n<strong>Jos olet oikealla asialla, [[Special:UserLogin|kirjaudu sisään]] ja yritä uudestaan.</strong>",
        "pagelanguage": "Sivun kielen valinta",
        "pagelang-name": "Sivu",
        "pagelang-language": "Kieli",
index 3a09b82..cf58229 100644 (file)
        "anoneditwarning": "<strong>Attention :</strong> Vous n’êtes pas connecté. Votre adresse IP sera visible de tout le monde si vous faites des modifications. Si vous <strong>[$1 vous connectez]</strong> ou <strong>[$2 créez un compte]</strong>, vos modifications seront attribuées à votre nom d’utilisateur, entre autres avantages.",
        "anonpreviewwarning": "''Vous n’êtes pas identifié(e). Sauvegarder enregistrera votre adresse IP dans l’historique des modifications de la page.''",
        "missingsummary": "'''Rappel :''' vous n'avez pas encore fourni le résumé de votre modification.\nSi vous cliquez de nouveau sur le bouton « {{int:savearticle}} », la publication sera faite sans nouvel avertissement.",
+       "selfredirect": "<strong>Attention :</strong> Vous êtes en train de créer une redirection vers le même article.\nSi vous cliquez de nouveau sur « {{int:savearticle}} », la redirection sera créée.",
        "missingcommenttext": "Veuillez entrer un commentaire ci-dessous.",
        "missingcommentheader": "'''Rappel :''' vous n'avez pas fourni de sujet ou de titre à ce commentaire.\nSi vous cliquez de nouveau sur « {{int:Savearticle}} », votre modification sera enregistrée sans titre.",
        "summary-preview": "Aperçu du résumé :",
index d90b777..4754b14 100644 (file)
@@ -43,7 +43,7 @@
        "tog-shownumberswatching": "Mostrar o número de usuarios que están a vixiar",
        "tog-oldsig": "Sinatura actual:",
        "tog-fancysig": "Tratar a sinatura como se fose texto wiki (sen ligazón automática)",
-       "tog-uselivepreview": "Usar a vista previa en tempo real (experimental)",
+       "tog-uselivepreview": "Usar a vista previa en tempo real",
        "tog-forceeditsummary": "Avisádeme cando o campo resumo estea baleiro",
        "tog-watchlisthideown": "Agochar as edicións propias na lista de vixilancia",
        "tog-watchlisthidebots": "Agochar as edicións dos bots na lista de vixilancia",
        "anoneditwarning": "<strong>Aviso:</strong> Non accedeu ao sistema. O seu enderezo IP será rexistado no histórico de edicións desta páxina. Se <strong>[$1 accede ao sistema]</strong> ou <strong>[$2 crea unha conta]</strong>, as súas edicións serán rexistadas co seu nome de usuario, ademais doutros beneficios.",
        "anonpreviewwarning": "''Non accedeu ao sistema. Se garda a páxina, o seu enderezo IP quedará rexistrado no historial de edicións.''",
        "missingsummary": "'''Aviso:''' Esqueceu incluír o texto do campo resumo.\nSe preme en \"{{int:savearticle}}\" a súa edición gardarase sen ningunha descrición da edición.",
+       "selfredirect": "<strong>Atención:</strong> Está a crear unha redireción cara o mesmo artigo. Se preme \"{{int:savearticle}}\" de novo, crearase a redireción.",
        "missingcommenttext": "Por favor, escriba un comentario a continuación.",
        "missingcommentheader": "'''Aviso:''' Non escribiu ningún texto no asunto/título deste comentario.\nSe preme sobre \"{{int:savearticle}}\", a súa edición gardarase sen el.",
        "summary-preview": "Vista previa do resumo:",
index f29b156..8564527 100644 (file)
        "protectedpagetext": "Ova stranica je zaključana da bi se onemogućile izmjene.",
        "viewsourcetext": "Možete pogledati i kopirati izvorni sadržaj ove stranice:",
        "viewyourtext": "Možete vidjeti i kopirati tekst '''vaših uređivanja''' na ovoj stranici:",
-       "protectedinterface": "Ova stranica je zaštićena od izmjena jer sadrži tekst MediaWiki softvera.\nAKo želite prevesti neprevedenu poruku ili popraviti prijevod neke druge poruke za sve MediaWiki wikije, posjetite [//translatewiki.net/  translatewiki.net], projekt za lokalizaciju MediaWiki softvera.",
+       "protectedinterface": "Ova stranica je zaštićena od izmjena jer sadrži tekst MediaWiki softvera.\nAko želite prevesti neprevedenu poruku ili popraviti prijevod neke druge poruke za sve MediaWiki wikije, posjetite [//translatewiki.net/  translatewiki.net], projekt za lokalizaciju MediaWiki softvera.",
        "editinginterface": "'''Upozorenje:''' Uređujete stranicu koja se rabi za prikaz teksta u sučelju softvera. Promjene učinjene na ovoj stranici će se odraziti na izgled korisničkog sučelja kod drugih suradnika. Za prijevod, razmotrite uporabu [//translatewiki.net/wiki/Main_Page?setlang=hr translatewiki.net], projekta lokalizacije MedijeWiki.",
+       "translateinterface": "Za dodavanje ili promjenu prijevoda za sve wikije koristite [//translatewiki.net/ translatewiki.net], projekt za lokalizaciju MediaWikija.",
        "cascadeprotected": "Ova je stranica zaključana za uređivanja jer je uključena u {{PLURAL:$1|slijedeću stranicu|slijedeće stranice}}, koje su zaštićene \"prenosivom zaštitom\":\n$2",
        "namespaceprotected": "Ne možete uređivati stranice u imenskom prostoru '''$1'''.",
        "customcssprotected": "Ne možete uređivati ovu CSS stranicu zato što ona sadrži osobne postavke drugog suradnika.",
        "download": "skidanje",
        "unwatchedpages": "Nepraćene stranice",
        "listredirects": "Popis preusmjeravanja",
+       "listduplicatedfiles": "Popis kopija datoteka",
+       "listduplicatedfiles-summary": "Ovo je popis datoteka kojima je zadnja inačica kopija zadnje inačice druge datoteke. Na popisu su samo lokalno postavljene datoteke.",
        "unusedtemplates": "Nekorišteni predlošci",
        "unusedtemplatestext": "Slijedi popis svih stranica imenskog prostora {{ns:template}}, koje nisu umetnute na drugim stranicama. Pripazite da prije brisanja provjerite druge poveznice koje vode na te predloške.",
        "unusedtemplateswlh": "druge poveznice",
        "pageinfo-category-pages": "Broj stranica",
        "pageinfo-category-subcats": "Broj podkategorija",
        "pageinfo-category-files": "Broj datoteka",
-       "markaspatrolleddiff": "Označi za pregledano",
+       "markaspatrolleddiff": "Označi pregledanim",
        "markaspatrolledtext": "Označi ovaj članak pregledanim",
        "markedaspatrolled": "Pregledano",
        "markedaspatrolledtext": "Odabrana promjena [[:$1]] označena je pregledanom.",
        "expand_templates_remove_comments": "Ukloni komentare",
        "expand_templates_remove_nowiki": "Ukloni <nowiki> tagove u rezultatima.",
        "expand_templates_generate_xml": "Prikaži XML stablo",
-       "expand_templates_preview": "Vidi kako će izgledati"
+       "expand_templates_preview": "Vidi kako će izgledati",
+       "mediastatistics": "Statistika datoteka",
+       "mediastatistics-summary": "Slijede statistike postavljenih datoteka koje pokazuju zadnju inačicu datoteke. Starije ili izbrisane inačice nisu prikazane."
 }
index 4b90435..00faf9d 100644 (file)
        "anoneditwarning": "<strong>Attenzione:</strong> Accesso non effettuato. Se effettuerai delle modifiche il tuo indirizzo IP sarà visibile pubblicamente. Se <strong>[$1 accedi]</strong> o <strong>[$2 crei un'utenza]</strong>, le tue modifiche saranno attribuite al tuo nome utente, insieme ad altri benefici.",
        "anonpreviewwarning": "''Non è stato eseguito il login. Salvando la pagina, il proprio indirizzo IP sarà registrato nella cronologia.''",
        "missingsummary": "'''Attenzione:''' non è stato specificato l'oggetto di questa modifica. Premendo di nuovo \"{{int:savearticle}}\" la modifica verrà salvata con l'oggetto vuoto.",
+       "selfredirect": "<strong>Attenzione:</strong> stai creando un redirect alla medesima voce.\nSe fai clic nuovamente su \"{{int:savearticle}}\", il redirect sarà creato.",
        "missingcommenttext": "Inserire un commento qui sotto.",
        "missingcommentheader": "'''Attenzione:''' non è stata specificato l'oggetto/l'intestazione di questo commento. Premendo di nuovo \"{{int:savearticle}}\" la modifica verrà salvata senza intestazione.",
        "summary-preview": "Anteprima dell'oggetto:",
index d70104e..9b54920 100644 (file)
@@ -48,7 +48,7 @@
        "tog-shownumberswatching": "მაკონტროლებელ მომხმარებელთა რიცხვის ჩვენება",
        "tog-oldsig": "არსებული ხელმოწერა:",
        "tog-fancysig": "საკუთარი ვიკიფორმატიანი ხელმოწერა (ავტომატური ბმულის გარეშე)",
-       "tog-uselivepreview": "გამოიყენეთ სწრაფი წინასწარი გადახედვა (ექსპერიმენტული)",
+       "tog-uselivepreview": "გამოიყენეთ სწრაფი წინასწარი გადახედვა",
        "tog-forceeditsummary": "გამაფრთხილე ცარიელი რედაქტირების რეზიუმეს შემთხვევაში",
        "tog-watchlisthideown": "დამალე ჩემი რედაქტირება კონტროლის სიაში",
        "tog-watchlisthidebots": "დამალე რობოტის რედაქტირება კონტროლის სიაში",
        "permalink": "მუდმივი ბმული",
        "print": "ამობეჭდე",
        "view": "იხილე",
+       "view-foreign": "იხილეთ $1-ზე",
        "edit": "რედაქტირება",
        "edit-local": "ლოკალური აღწერის რედაქტირება",
        "create": "შექმნა",
        "otherlanguages": "სხვა ენებზე",
        "redirectedfrom": "(გადმომისამართდა $1-დან)",
        "redirectpagesub": "გადამისამართება გვერდზე",
+       "redirectto": "გადამისამართება:",
        "lastmodifiedat": "ეს გვერდი ბოლოს განახლდა $2, $1.",
        "viewcount": "ეს გვერდი შემოწმდა {{PLURAL:$1|ერთხელ|$1-ჯერ}}.",
        "protectedpage": "დაბლოკილი გვერდი",
        "viewsourcetext": "თქვენ შეგიძლიათ ნახოთ ამ გვერდის საწყისი ფაილი და მისი ასლი შექმნათ:",
        "viewyourtext": "თქვენ შეგიძლიათ იხილოთ და დააკოპიროთ  '''თქვენი რედაქტირებების''' საწყისი ტექსტი ამ გვერდზე:",
        "protectedinterface": "ეს გვერდი წარმოადგენს ტექსტურ ინტერფეისს პროგრამული უზრუნველყოფისათვის და დაცულია ვანდალიზმის აღკვეთის მიზნით.",
-       "editinginterface": "'''á\83§á\83£á\83 á\83\90á\83\93á\83¦á\83\94á\83\91á\83\90:''' á\83\97á\83¥á\83\95á\83\94á\83\9c á\83 á\83\94á\83\93á\83\90á\83¥á\83¢á\83\9dá\83 á\83\9dá\83\91á\83\97 á\83\92á\83\95á\83\94á\83 á\83\93á\83¡, á\83 á\83\9dá\83\9bá\83\94á\83\9aá\83\98á\83ª á\83\9eá\83 á\83\9dá\83\92á\83 á\83\90á\83\9bá\83\98á\83¡ á\83\98á\83\9cá\83¢á\83\94á\83 á\83¤á\83\94á\83\98á\83¡á\83\98á\83¡ á\83¢á\83\94á\83¥á\83¡á\83¢á\83¡ á\83¨á\83\94á\83\98á\83ªá\83\90á\83\95á\83¡. \ná\83\90á\83\9b á\83\92á\83\95á\83\94á\83 á\83\93á\83\96á\83\94 á\83\92á\83\90á\83\9cá\83®á\83\9dá\83 á\83ªá\83\98á\83\94á\83\9aá\83\94á\83\91á\83£á\83\9aá\83\98 á\83 á\83\94á\83\93á\83\90á\83¥á\83¢á\83\98á\83 á\83\94á\83\91á\83\90 á\83\92á\83\90á\83\9bá\83\9dá\83\98á\83¬á\83\95á\83\94á\83\95á\83¡ á\83\90á\83\9b á\83\95á\83\98á\83\99á\83\98á\83¡ á\83¡á\83®á\83\95á\83\90 á\83\9bá\83\9dá\83\9bá\83®á\83\9bá\83\90á\83 á\83\94á\83\91á\83\94á\83\9aá\83\97á\83\90 á\83¡á\83\90á\83\9bá\83£á\83¨á\83\90á\83\9d á\83\98á\83\9cá\83¢á\83\94á\83 á\83¤á\83\94á\83\98á\83¡á\83\98á\83¡ á\83¨á\83\94á\83ªá\83\95á\83\9aá\83\90á\83¡á\83\90á\83ª. \ná\83\98á\83\9bá\83\98á\83¡á\83\90á\83\97á\83\95á\83\98á\83¡, á\83 á\83\9dá\83\9b á\83\93á\83\90á\83\90á\83\9bá\83\90á\83¢á\83\9dá\83\97 á\83\90á\83\9c á\83¨á\83\94á\83ªá\83\95á\83\90á\83\9aá\83\9dá\83\97 á\83\97á\83\90á\83 á\83\92á\83\9bá\83\90á\83\9cá\83\94á\83\91á\83\98 á\83§á\83\95á\83\94á\83\9aá\83\90 á\83\95á\83\98á\83\99á\83\98á\83¨á\83\98 გთხოვთ, გამოიყენოთ მედიავიკის ლოკალიზაციის პროექტი [//translatewiki.net/ translatewiki.net].",
+       "editinginterface": "'''á\83§á\83£á\83 á\83\90á\83\93á\83¦á\83\94á\83\91á\83\90:''' á\83\97á\83¥á\83\95á\83\94á\83\9c á\83\90á\83 á\83\94á\83\93á\83\90á\83¥á\83¢á\83\98á\83 á\83\94á\83\91á\83\97 á\83\92á\83\95á\83\94á\83 á\83\93á\83¡, á\83 á\83\9dá\83\9bá\83\94á\83\9aá\83\98á\83ª á\83\9eá\83 á\83\9dá\83\92á\83 á\83\90á\83\9bá\83\98á\83¡ á\83\98á\83\9cá\83¢á\83\94á\83 á\83¤á\83\94á\83\98á\83¡á\83\98á\83¡ á\83¢á\83\94á\83¥á\83¡á\83¢á\83¡ á\83¨á\83\94á\83\98á\83ªá\83\90á\83\95á\83¡. \ná\83\90á\83\9b á\83\92á\83\95á\83\94á\83 á\83\93á\83\96á\83\94 á\83\92á\83\90á\83\9cá\83®á\83\9dá\83 á\83ªá\83\98á\83\94á\83\9aá\83\94á\83\91á\83£á\83\9aá\83\98 á\83 á\83\94á\83\93á\83\90á\83¥á\83¢á\83\98á\83 á\83\94á\83\91á\83\90 á\83\92á\83\90á\83\9bá\83\9dá\83\98á\83¬á\83\95á\83\94á\83\95á\83¡ á\83\90á\83\9b á\83\95á\83\98á\83\99á\83\98á\83¡ á\83¡á\83®á\83\95á\83\90 á\83\9bá\83\9dá\83\9bá\83®á\83\9bá\83\90á\83 á\83\94á\83\91á\83\94á\83\9aá\83\97á\83\90 á\83¡á\83\90á\83\9bá\83£á\83¨á\83\90á\83\9d á\83\98á\83\9cá\83¢á\83\94á\83 á\83¤á\83\94á\83\98á\83¡á\83\98á\83¡ á\83¨á\83\94á\83ªá\83\95á\83\9aá\83\90á\83¡á\83\90á\83ª. \ná\83\98á\83\9bá\83\98á\83¡á\83\90á\83\97á\83\95á\83\98á\83¡, á\83 á\83\9dá\83\9b á\83\93á\83\90á\83\90á\83\9bá\83\90á\83¢á\83\9dá\83\97 á\83\90á\83\9c á\83¨á\83\94á\83ªá\83\95á\83\90á\83\9aá\83\9dá\83\97 á\83\97á\83\90á\83 á\83\92á\83\9bá\83\90á\83\9cá\83\94á\83\91á\83\98 á\83§á\83\95á\83\94á\83\9aá\83\90 á\83\95á\83\98á\83\99á\83\98á\83¨á\83\98, გთხოვთ, გამოიყენოთ მედიავიკის ლოკალიზაციის პროექტი [//translatewiki.net/ translatewiki.net].",
        "cascadeprotected": "ეს გვერდი რედაქტირებისგან დაცულია, რადგან იგი ჩართულია შემდეგ {{PLURAL:$1|გვერდში, რომლის |გვერდებში, რომელთა}} დასაცავადაც ჩართულია პარამეტრი \"იერარქიული\":\n$2",
        "namespaceprotected": "თქვენ არ გაქვთ '''$1''' სახელთა სივრცეში გვერდების რედაქტირების უფლება.",
        "customcssprotected": "თქვენ არ გაქვთ ამ CSS გვერდის რედაქტირების უფლება, ვინაიდან ის სხვა მომხმარებლის პირად კონფიგურაციას შეიცავს.",
index af5ceec..282de51 100644 (file)
@@ -43,7 +43,7 @@
        "tog-shownumberswatching": "D'Zuel vun de Benotzer déi dës Säit iwwerwaache weisen",
        "tog-oldsig": "Aktuell Ënnerschrëft:",
        "tog-fancysig": "Ënnerschrëft als Wiki-Text behandelen (Ouni automatesche Link)",
-       "tog-uselivepreview": "Live-Preview benotzen (experimentell)",
+       "tog-uselivepreview": "Live-Preview benotzen",
        "tog-forceeditsummary": "Warnen, wa beim Späicheren de Resumé feelt",
        "tog-watchlisthideown": "Meng Ännerungen op menger Iwwerwaachungslëscht verstoppen",
        "tog-watchlisthidebots": "Ännerunge vu Botten op menger Iwwerwaachungslëscht verstoppen",
index 4158342..139f3c1 100644 (file)
@@ -43,7 +43,7 @@
        "tog-shownumberswatching": "Прикажи го бројот на корисници кои набљудуваат",
        "tog-oldsig": "Постоечки потпис:",
        "tog-fancysig": "Сметај го потписот за викитекст (без автоматска врска)",
-       "tog-uselivepreview": "Користи преглед во живо (експериментално)",
+       "tog-uselivepreview": "Користи преглед во живо",
        "tog-forceeditsummary": "Извести ме кога нема опис на промените",
        "tog-watchlisthideown": "Скриј мои уредувања од списокот на набљудувања",
        "tog-watchlisthidebots": "Скриј ботовски уредувања од списокот на набљудувања",
        "anoneditwarning": "<strong>Предупредување:</strong> Не сте најавени. Вашата IP-адреса ќе биде јавно видлива ако уредувате. Ако <strong>[$1 се најавите]</strong> или <strong>[$2 направите сметка]</strong>, тогаш уредувањата ќе се припишуваат на вашето корисничко име, покрај другите погодности.",
        "anonpreviewwarning": "''Не сте најавени. Ако ја зачувате, Вашата IP-адреса ќе биде заведена во историјата на уредување на страницата.''",
        "missingsummary": "'''Потсетник:''' Не внесовте опис на измените. Ако притиснете Зачувај повторно, вашите измени ќе се зачуваат без опис.",
+       "selfredirect": "<strong>Предупредување:</strong> Создавате пренасочување кон истата статија.\nАко стиснете на „{{int:savearticle}}“ повторно, тогаш пренасочувањето ќе се создаде.",
        "missingcommenttext": "Ве молиме внесете коментар подолу.",
        "missingcommentheader": "'''Потсетување:''' Не внесовте наслов за овој коментар.\nАко повторно стиснете на „{{int:savearticle}}“, уредувањето ќе биде зачувано без наслов.",
        "summary-preview": "Изглед на описот:",
        "pager-older-n": "{{PLURAL:$1|постара 1|постари $1}}",
        "suppress": "Скривање",
        "querypage-disabled": "Оваа службена страница е оневозможена за да не попречува на делотворноста.",
-       "apihelp": "Ð\9fомоÑ\88 Ñ\81о Ð¿Ñ\80илогот",
+       "apihelp": "Ð\9fомоÑ\88 Ñ\81о Ð¸Ð·Ð²Ñ\80Ñ\88никот",
        "apihelp-no-such-module": "Модулот „$1“ не е пронајден.",
        "booksources": "Печатени извори",
        "booksources-search-legend": "Пребарување на извори за книга",
        "version-parserhooks": "Расчленувачки куки",
        "version-variables": "Променливи",
        "version-antispam": "Спречување на спам",
-       "version-api": "Ð\9fÑ\80илози",
+       "version-api": "Ð\98звÑ\80Ñ\88ниÑ\86и",
        "version-other": "Друго",
        "version-mediahandlers": "Ракувачи со мултимедијални содржини",
        "version-hooks": "Куки",
        "feedback-cancel": "Откажи",
        "feedback-submit": "Поднеси мислење",
        "feedback-adding": "Го додавам искажаното мислење во страницата...",
-       "feedback-error1": "Ð\93Ñ\80еÑ\88ка: Ð\9dепÑ\80епознаен Ñ\80езÑ\83лÑ\82аÑ\82 Ð¾Ð´ Ð¿Ñ\80илогот (API)",
+       "feedback-error1": "Ð\93Ñ\80еÑ\88ка: Ð\9dепÑ\80епознаен Ñ\80езÑ\83лÑ\82аÑ\82 Ð¾Ð´ Ð¸Ð·Ð²Ñ\80Ñ\88никот (API)",
        "feedback-error2": "Грешка: Уредувањето не успеа",
-       "feedback-error3": "Ð\93Ñ\80еÑ\88ка: Ð\9fÑ\80илогоÑ\82 (API) не одговара",
+       "feedback-error3": "Ð\93Ñ\80еÑ\88ка: Ð\98звÑ\80Ñ\88никоÑ\82 не одговара",
        "feedback-thanks": "Благодариме! Вашиот одѕив е објавен на страницата „[$2 $1]“.",
        "feedback-close": "Готово",
        "feedback-bugcheck": "Одлично! Само проверете да не е една од [$1 веќе познатите грешки].",
index 6fdd349..b7481e9 100644 (file)
@@ -55,7 +55,7 @@
        "tog-shownumberswatching": "ശ്രദ്ധിക്കുന്ന ഉപയോക്താക്കളുടെ എണ്ണം കാണിക്കുക",
        "tog-oldsig": "നിലവിലുള്ള ഒപ്പ്:",
        "tog-fancysig": "ഒപ്പ് ഒരു വിക്കി എഴുത്തായി പരിഗണിക്കുക (കണ്ണി സ്വയം ചേർക്കേണ്ടതില്ല)",
-       "tog-uselivepreview": "തത്സമയ പ്രിവ്യൂ ഉപയോഗപ്പെടുത്തുക (പരീക്ഷണാടിസ്ഥാനം)",
+       "tog-uselivepreview": "തത്സമയ പ്രിവ്യൂ ഉപയോഗപ്പെടുത്തുക",
        "tog-forceeditsummary": "തിരുത്തുകളുടെ ചുരുക്കം നൽകിയില്ലെങ്കിൽ എന്നെ ഓർമ്മിപ്പിക്കുക",
        "tog-watchlisthideown": "ഞാൻ ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിൽനിന്ന് എന്റെ തിരുത്തുകൾ മറയ്ക്കുക",
        "tog-watchlisthidebots": "ഞാൻ ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിൽനിന്ന് യന്ത്രങ്ങൾ വരുത്തിയ തിരുത്തുകൾ മറയ്ക്കുക",
        "anoneditwarning": "<strong>മുന്നറിയിപ്പ്:</strong> താങ്കൾ ലോഗിൻ ചെയ്തിട്ടില്ല. താങ്കൾ തിരുത്തുകളെന്തെങ്കിലും ചെയ്യുകയാണെങ്കിൽ താങ്കളുടെ ഐ.പി. വിലാസം എല്ലാവർക്കും ലഭ്യമായിരിക്കും. താങ്കൾ <strong>[$1 ലോഗിൻ ചെയ്യുകയോ]</strong>  <strong>[$2 അംഗത്വമെടുക്കുകയോ]</strong> ചെയ്യുന്നതുവഴി മറ്റ് ഗുണങ്ങളോടൊപ്പം താങ്കളുടെ തിരുത്തുകൾ ഉപയോക്തൃനാമത്തിലാവും അറിയപ്പെടുക.",
        "anonpreviewwarning": "''താങ്കൾ ലോഗിൻ ചെയ്തിട്ടില്ല. സേവ് ചെയ്യുമ്പോൾ താളിന്റെ തിരുത്തൽ ചരിത്രത്തിൽ താങ്കളുടെ ഐ.പി. വിലാസം ചേർത്തു സൂക്ഷിക്കപ്പെടും.''",
        "missingsummary": "'''ഓർമ്മക്കുറിപ്പ്:''' താങ്കൾ തിരുത്തലിന്റെ ചുരുക്കരൂപം നൽകിയിട്ടില്ല. ''സേവ് ചെയ്യുക'' ബട്ടൺ ഒരുവട്ടം കൂടി അമർത്തിയാൽ താങ്കൾ വരുത്തിയ മാറ്റം കാത്തുസൂക്ഷിക്കുന്നതാണ്.",
+       "selfredirect": "<strong>മുന്നറിയിപ്പ്:</strong> അതേ ലേഖനത്തിലേക്കുള്ള തിരിച്ചുവിടലാണ് താങ്കൾ സൃഷ്ടിക്കുന്നത്.\nവീണ്ടും \"{{int:savearticle}}\" അമർത്തിയാൽ, തിരിച്ചുവിടൽ സൃഷ്ടിക്കപ്പെടുന്നതാണ്.",
        "missingcommenttext": "താങ്കളുടെ അഭിപ്രായം ദയവായി താഴെ രേഖപ്പെടുത്തുക.",
        "missingcommentheader": "'''ഓർമ്മക്കുറിപ്പ്:''' ഈ കുറിപ്പിന് താങ്കൾ വിഷയം/തലക്കെട്ട് നൽകിയിട്ടില്ല. ''{{int:savearticle}}'' എന്ന ബട്ടൺ ഒരുവട്ടം കൂടി അമർത്തിയാൽ വിഷയം/തലക്കെട്ട് ഇല്ലാതെ തന്നെ കാത്തുസൂക്ഷിക്കുന്നതാവും.",
        "summary-preview": "ചുരുക്കരൂപം എങ്ങനെയുണ്ടെന്നു കാണുക:",
index db74b13..bbe6a1c 100644 (file)
@@ -38,7 +38,7 @@
        "tog-shownumberswatching": "Fa' vedé 'o nummero d'utente che teneno 'a paggena cuntrullata",
        "tog-oldsig": "Firma 'e mmo:",
        "tog-fancysig": "Piglia 'a firma comme fosse nu wikitesto (senza fà link automatico)",
-       "tog-uselivepreview": "Abilita 'o \"Live preview\" (sperimentale)",
+       "tog-uselivepreview": "Abbìa 'o \"Live preview\"",
        "tog-forceeditsummary": "Chiere a mme quanno se sta azzeccanno nu campo oggetto abbacante",
        "tog-watchlisthideown": "Annascunne 'e cagnamiente d' 'a lista 'e cuntrollo mia",
        "tog-watchlisthidebots": "Annasconne 'e cagnamiènte d' 'e bot ncopp'a l'elenco 'e cuntrollo",
        "anoneditwarning": "'''Attenzione:''' Nun avite fatto l'acciesso. 'A cronologgia d' 'a vosta sarrà visibbele pubbrecamente si facite cocche cagnamiento. Si <strong>[$1 tràse]</strong> o <strong>[$2 crìe nu cunto]</strong>, 'e cagnamiente vuoste ve sarranno attribbuite a vvuje, nzieme a n'ati migliuramente.",
        "anonpreviewwarning": "''Nun avite fatto 'o login. Sarvann' 'a paggena, l'indirizzo IP d' 'o vuosto sarrà riggistrato dint'a cronologgia.''",
        "missingsummary": "'''Attenziò:''' nun s'è specificato l'oggetto 'e stu cagnamiento. Clicann' 'a \"{{int:savearticle}}\" n'ata vota 'o cagnamiento sarrà sarvato cu l'oggetto abbacante.",
+       "selfredirect": "<strong>Attenziò:</strong> State crianno nu redirect a 'o stesso articolo.\nSi cliccate \"{{int:savearticle}}\" n'ata vota, si criarrà 'o redirect.",
        "missingcommenttext": "Pe' piacere scrivete nu commento ccà abbascio.",
        "missingcommentheader": "'''Attenziò:''' nun s'è specificato l'oggetto/titolo 'e stu commento. Clicann' 'a \"{{int:savearticle}}\" n'ata vota 'o cagnamiento sarrà sarvato c' 'o titolo abbacante.",
        "summary-preview": "Anteprimma'e l'oggetto:",
index 304c515..05afab3 100644 (file)
@@ -42,7 +42,7 @@
        "tog-shownumberswatching": "Smon-e ël nùmer d'utent che as ten-o la pàgina sot-euj",
        "tog-oldsig": "Firma esistenta:",
        "tog-fancysig": "Traté la firma com dël test wiki (sensa n'anliura automàtica)",
-       "tog-uselivepreview": "Dovré la fonsion ''Preuva dal viv'' (sperimental)",
+       "tog-uselivepreview": "Dovré la fonsion ''Preuva dal viv''",
        "tog-forceeditsummary": "Ciamé conferma se ël resumé dla modìfica a l'é veujd",
        "tog-watchlisthideown": "Stërmé mie modìfiche ant la ròba che im ten-o sot-euj",
        "tog-watchlisthidebots": "Stërmé le modìfiche fàite daj trigomiro ant la lista dle ròbe che im ten-o sot-euj",
        "anoneditwarning": "<strong>Atension:<strong> A l'é nen rintrà ant ël sistema. Soa adrëssa IP a së sc-iairërà s'a fà dle modìfiche. Si chiel a <strong>[$1 rintra ant ël sistema]</strong> o <strong>[$2 a crea an cont]</strong>, soe modìfiche a saran atribuìe a sò stranòm, ansema a d'àutri vantagg.",
        "anonpreviewwarning": "''A l'é nen rintrà ant ël sistema. An salvand a sarà memorisà soa adrëssa IP ant la stòria dle modìfiche ëd sa pàgina.''",
        "missingsummary": "'''Nòta:''' a l'ha butà gnun resumé dla modìfica. Se a sgnaca «{{int:savearticle}}» n'àutra vira, soa modìfica a resterà salvà sensa resumé.",
+       "selfredirect": "<strong>Atension:</strong> A l'é an camin ch'a crea na ridiriression a l'istess artìcol.\nS'a sgnaca torna ansima a «{{int:savearticle}}», la ridiression a sarà creà.",
        "missingcommenttext": "Për piasì, che a buta un coment sì-sota.",
        "missingcommentheader": "'''Ch'a arcòrda:''' A l'ha pa dàit ëd soget o d'intestassion për cost coment.\nSe a sgnaca torna «{{int:savearticle}}», soa modìfica a sarà salvà sensa gnun-a intestassion.",
        "summary-preview": "Preuva dël resumé:",
index 2e5e461..ff387d9 100644 (file)
        "anoneditwarning": "<strong>Atenție:</strong> Nu v-ați autentificat. Adresa dumneavoastră IP va fi vizibilă în mod public dacă efectuați modificări. Dacă vă <strong>[$1 autentificați]</strong> sau vă <strong>[$2 creați un cont]</strong>, modificările dumneavoastră vor fi asociate numelui de utilizator, pe lângă alte beneficii.",
        "anonpreviewwarning": "''Nu v-ați autentificat. Dacă salvați pagina adresa dumneavoastră IP va fi înregistrată în istoric.''",
        "missingsummary": "'''Atenție:''' Nu ați completat caseta „descriere modificări”. Dacă apăsați din nou butonul „salvează pagina” modificările vor fi salvate fără descriere.",
+       "selfredirect": "<strong>Atenție:</strong> Sunteți pe cale să creați o redirecționare către același articol.\nDacă apăsați din nou pe „{{int:savearticle}}”, redirecționarea va fi creată.",
        "missingcommenttext": "Vă rugăm să introduceți un comentariu.",
        "missingcommentheader": "'''Atenție,''' nu ați pus titlu sau subiect la acest comentariu.\nDacă dați din nou clic pe „{{int:savearticle}}” modificarea va fi salvată fără titlu.",
        "summary-preview": "Previzualizare descriere:",
index 412fc0c..6f83e8e 100644 (file)
        "tog-shownumberswatching": "Показывать число участников, включивших страницу в свой список наблюдения",
        "tog-oldsig": "Текущая подпись:",
        "tog-fancysig": "Собственная вики-разметка подписи (без автоматической ссылки)",
-       "tog-uselivepreview": "Использовать быстрый предварительный просмотр (экспериментально)",
+       "tog-uselivepreview": "Использовать быстрый предварительный просмотр",
        "tog-forceeditsummary": "Предупреждать, когда не заполнено поле описания правки",
        "tog-watchlisthideown": "Скрывать мои правки из списка наблюдения",
        "tog-watchlisthidebots": "Скрывать правки ботов из списка наблюдения",
index bc5d8c5..a965ded 100644 (file)
        "anoneditwarning": "<strong>Opozorilo:</strong> Niste prijavljeni. Vaš IP-naslov bo javno viden, če naredite kakršno koli urejanje. Če se <strong>[$1 prijavite]</strong> ali <strong>[$2 ustvarite račun]</strong>, bodo vaša urejanja pripisana vašemu uporabniškemu imenu skupaj z drugimi prednostmi.",
        "anonpreviewwarning": "Niste prijavljeni. Ob spremembi strani se bo vaš IP-naslov zapisal v zgodovini urejanja te strani.",
        "missingsummary": "'''Opozorilo:''' Niste napisali povzetka urejanja. Ob ponovnem kliku gumba ''Shrani'' se bo vaše urejanje shranilo brez njega.",
+       "selfredirect": "<strong>Opozorilo:</strong> Ustvarjate preusmeritev na isti članek.\nČe ponovno kliknete »{{int:savearticle}}«, bomo preusmeritev ustvarili.",
        "missingcommenttext": "Prosimo, vpišite v spodnje polje komentar.",
        "missingcommentheader": "'''Opozorilo:''' Niste vnesli zadeve/naslova za ta komentar.\nČe boste ponovno kliknili »{{int:savearticle}}«, bo vaše urejanje shranjeno brez le-tega.",
        "summary-preview": "Predogled povzetka",
index 9625cb6..6f52692 100644 (file)
@@ -88,7 +88,7 @@
        "tog-shownumberswatching": "Visa antalet användare som bevakar",
        "tog-oldsig": "Nuvarande signatur:",
        "tog-fancysig": "Behandla signatur som wikitext (utan en automatisk länk)",
-       "tog-uselivepreview": "Använd direktuppdaterad förhandsgranskning (experimentell)",
+       "tog-uselivepreview": "Använd direktuppdaterad förhandsgranskning",
        "tog-forceeditsummary": "Påminn mig om jag inte fyller i en redigeringskommentar",
        "tog-watchlisthideown": "Dölj mina redigeringar i bevakningslistan",
        "tog-watchlisthidebots": "Visa inte robotredigeringar i bevakningslistan",
        "anoneditwarning": "<strong>Varning:</strong> Du är inte inloggad. Din IP-adress kommer att vara publikt synlig om du gör några redigeringar. Om du <strong>[$1 loggar in]</strong> eller <strong>[$2 skapar ett konto]</strong> kommer dina redigeringar att tillskrivas ditt användarnamn, tillsammans med andra fördelar.",
        "anonpreviewwarning": "''Du är inte inloggad. Om du sparar kommer din IP-adress registreras på denna sidas redigeringshistorik.''",
        "missingsummary": "<strong>Påminnelse:</strong> Du har inte skrivit någon redigeringskommentar.\nOm du klickar på \"{{int:savearticle}}\" igen kommer din redigering att sparas utan en sådan.",
+       "selfredirect": "<strong>Varning:</strong> Du omdirigerar till samma artikel.\nOm du klickar på \"{{int:savearticle}}\" igen kommer omdirigeringen att skapas.",
        "missingcommenttext": "Var god och skriv in en kommentar nedan.",
        "missingcommentheader": "<strong>Påminnelse:</strong> Du har inte skrivit något ämne/rubrik för den här kommentaren.\nOm du trycker på \"{{int:savearticle}}\" igen kommer din redigering sparas utan rubrik.",
        "summary-preview": "Förhandsgranskning av sammanfattning:",
index 14ebeaf..67346b3 100644 (file)
@@ -47,7 +47,7 @@
        "tog-shownumberswatching": "వీక్షకుల సంఖ్యను చూపు",
        "tog-oldsig": "ప్రస్తుత సంతకం:",
        "tog-fancysig": "సంతకాన్ని వికీపాఠ్యంగా తీసుకో (ఆటోమెటిక్‌ లింకు లేకుండా)",
-       "tog-uselivepreview": "à°µà±\86à°¨à±\81à°µà±\86à°\82à°\9f à°®à±\81à°¨à±\81à°\9cà±\82à°ªà±\81à°¨à±\81 à°µà°¾à°¡à±\81 (à°ªà±\8dà°°à°¯à±\8bà°\97ాతà±\8dà°®à°\95à°\82)",
+       "tog-uselivepreview": "తాà°\9cà°¾ à°®à±\81à°¨à±\81à°\9cà±\82à°ªà±\81à°¨à±\81 à°µà°¾à°¡à±\81",
        "tog-forceeditsummary": "దిద్దుబాటు సారాంశం ఖాళీగా ఉంటే ఆ విషయాన్ని నాకు సూచించు",
        "tog-watchlisthideown": "నా మార్పులను వీక్షణా జాబితాలో చూపించొద్దు",
        "tog-watchlisthidebots": "బాట్లు చేసిన మార్పులను నా వీక్షణా జాబితాలో చూపించొద్దు",
        "hidetoc": "దాచు",
        "collapsible-collapse": "కుదించు",
        "collapsible-expand": "విస్తరించు",
+       "confirmable-yes": "అవును",
+       "confirmable-no": "కాదు",
        "thisisdeleted": "$1ను చూస్తారా, పునఃస్థాపిస్తారా?",
        "viewdeleted": "$1 చూస్తారా?",
        "restorelink": "{{PLURAL:$1|ఒక తొలగించిన మార్పు|$1 తొలగించిన మార్పులు}}",
        "search-result-category-size": "{{PLURAL:$1|1 సభ్యుడు|$1 సభ్యులు}} ({{PLURAL:$2|1 ఉవవర్గం|$2 ఉపవర్గాలు}}, {{PLURAL:$3|1 దస్త్రం|$3 దస్త్రాలు}})",
        "search-redirect": "(దారిమార్పు $1)",
        "search-section": "(విభాగం $1)",
+       "search-category": "(వర్గం $1)",
        "search-file-match": "(ఫైలు విషయంతో సరిపోలుతోంది)",
        "search-suggest": "మీరు అంటున్నది ఇదా: $1",
        "search-interwiki-caption": "సోదర ప్రాజెక్టులు",
        "license-nopreview": "(మునుజూపు అందుబాటులో లేదు)",
        "upload_source_url": " (సార్వజనికంగా అందుబాటులో ఉన్న, సరైన URL)",
        "upload_source_file": " (మీ కంప్యూటర్లో ఒక ఫైలు)",
+       "listfiles-delete": "తొలగించు",
        "listfiles-summary": "ఈ ప్రత్యేక పేజీ, ఎక్కించిన ఫైళ్ళన్నిటినీ చూపిస్తుంది.",
        "listfiles_search_for": "మీడియా పేరుకై వెతుకు:",
        "imgfile": "దస్త్రం",
        "randomincategory": "వర్గంలోని యాదృచ్చిక పేజీ",
        "randomincategory-invalidcategory": "\"$1\" అనేది సరైన పర్గం పేరు కాదు.",
        "randomincategory-nopages": "[[:Category:$1|$1]] వర్గంలో పేజీలేమీ లేవు.",
+       "randomincategory-category": "వర్గం:",
        "randomredirect": "యాదృచ్చిక దారిమార్పు",
        "randomredirect-nopages": "\"$1\" పేరుబరిలో దారిమార్పులేమీ లేవు.",
        "statistics": "గణాంకాలు",
        "querypage-disabled": "పనితీరు కారణాల వలన, ఈ ప్రత్యేకపేజీని అశక్తం చేసాం.",
        "booksources": "పుస్తక మూలాలు",
        "booksources-search-legend": "పుస్తక మూలాల కోసం వెతుకు",
+       "booksources-search": "వెతుకు",
        "booksources-text": "కొత్త, పాత పుస్తకాలు అమ్మే ఇతర సైట్లకు లింకులు కింద ఇచ్చాం. మీరు వెతికే పుస్తకాలకు సంబంధించిన మరింత సమాచారం కూడా అక్కడ దొరకొచ్చు:",
        "booksources-invalid-isbn": "మీరిచ్చిన ISBN సరైనదిగా అనిపించుటలేదు; అసలు మూలాన్నుండి కాపీ చేయడంలో పొరపాట్లున్నాయేమో చూసుకోండి.",
        "specialloguserlabel": "కర్త:",
        "confirm-watch-top": "ఈ పుటను మీ వీక్షణ జాబితాలో చేర్చాలా?",
        "confirm-unwatch-button": "సరే",
        "confirm-unwatch-top": "ఈ పుటను మీ వీక్షణ జాబితా నుండి తొలగించాలా?",
+       "quotation-marks": "“$1”",
        "imgmultipageprev": "← మునుపటి పేజీ",
        "imgmultipagenext": "తరువాతి పేజీ →",
        "imgmultigo": "వెళ్ళు!",
        "autosumm-replace": "పేజీని '$1' తో మారుస్తున్నాం",
        "autoredircomment": "[[$1]]కు దారిమళ్ళించారు",
        "autosumm-new": "'$1' తో కొత్త పేజీని సృష్టించారు",
+       "autosumm-newblank": "ఖాళీ పేజీని సృష్టించారు",
        "lag-warn-normal": "$1 {{PLURAL:$1|క్షణం|క్షణాల}} లోపు జరిగిన మార్పులు ఈ జాబితాలో కనిపించకపోవచ్చు.",
        "lag-warn-high": "అధిక వత్తిడి వలన డేటాబేసు సర్వరు వెనుకబడింది, $1 {{PLURAL:$1|క్షణం|క్షణాల}} కంటే కొత్తవైన మార్పులు ఈ జాబితాలో కనిపించకపోవచ్చు.",
        "watchlistedit-normal-title": "వీక్షణ జాబితాను మార్చు",
        "duplicate-defaultsort": "హెచ్చరిక: డిఫాల్టు పేర్చు కీ \"$2\", గత డిఫాల్టు పేర్చు కీ \"$1\" ని అతిక్రమిస్తుంది.",
        "version": "సంచిక",
        "version-extensions": "స్థాపించిన పొడగింతలు",
-       "version-skins": "అలంకారాలు",
+       "version-skins": "à°¸à±\8dథాపిà°\82à°\9aà°¿à°¨ à°\85à°²à°\82à°\95ారాలà±\81",
        "version-specialpages": "ప్రత్యేక పేజీలు",
        "version-parserhooks": "పార్సరు కొక్కాలు",
        "version-variables": "చరరాశులు",
        "version-hook-name": "కొక్కెం పేరు",
        "version-hook-subscribedby": "ఉపయోగిస్తున్నవి",
        "version-version": "(కూర్పు $1)",
+       "version-no-ext-name": "[పేరు లేదు]",
        "version-license": "MediaWiki లైసెన్సు",
        "version-ext-license": "లైసెన్సు",
        "version-ext-colheader-name": "పొడిగింత",
+       "version-skin-colheader-name": "అలంకారం",
        "version-ext-colheader-version": "కూర్పు",
        "version-ext-colheader-license": "లైసెన్సు",
        "version-ext-colheader-description": "వివరణ",
        "specialpages-group-wiki": "డాటా మరియు పనిముట్లు",
        "specialpages-group-redirects": "ప్రత్యేక పేజీల దారిమార్పులు",
        "specialpages-group-spam": "స్పామ్ పనిముట్లు",
+       "specialpages-group-developer": "వికాసకుల పనిముట్లు",
        "blankpage": "ఖాళీ పేజీ",
        "intentionallyblankpage": "బెంచిమార్కింగు, మొదలగు వాటికై ఈ పేజీని కావాలనే ఖాళీగా వదిలాము.",
        "external_image_whitelist": " #ఈ లైనును ఎలా ఉన్నదో అలాగే వదిలెయ్యండి<pre>\n#regular expression తునకలను (// ల మధ్య ఉండే భాగం)కింద పెట్టండి\n#వీటిని బయటి బొమ్మల URLలతో సరిపోల్చుతాము\n#సరిపోలిన బొమ్మలను చూపిస్తాము, మిగిలినవాటి లింకులను మాత్రమే చూపిస్తాము\n##తో మొదలయ్యే లైనులు వ్యాఖ్యానాలుగా భావించబడతాయి\n#ఇది కేస్-సెన్సిటివ్\n\n#అన్ని తునకలను ఈ లైనుకు పైన ఉంచండి.  ఈ లైనును ఎలా ఉన్నదో అలాగే వదిలెయ్యండి</pre>",
        "expand_templates_remove_nowiki": "ఫలితంలో <nowiki> ట్యాగులను అణచిపెట్టు",
        "expand_templates_generate_xml": "XML పార్స్ ట్రీని చూపించు",
        "expand_templates_generate_rawhtml": "ముడి HTML ను చూపించు",
-       "expand_templates_preview": "మునుజూపు"
+       "expand_templates_preview": "మునుజూపు",
+       "pagelang-name": "పేజీ",
+       "pagelang-language": "భాష",
+       "pagelang-use-default": "అప్రమేయ భాషను వాడు"
 }
index 88defd0..87b513c 100644 (file)
@@ -48,7 +48,7 @@
        "tog-shownumberswatching": "แสดงจำนวนผู้ใช้ที่เฝ้าดู",
        "tog-oldsig": "ลายเซ็นที่ใช้อยู่:",
        "tog-fancysig": "ถือลายเซ็นเป็นข้อความวิกิ (โดยไม่มีลิงก์อัตโนมัติ)",
-       "tog-uselivepreview": "à¹\83à¸\8aà¹\89à¸\95ัวอยà¹\88าà¸\87à¸\97ัà¸\99à¸\97ี (à¸\97à¸\94ลอà¸\87)",
+       "tog-uselivepreview": "à¹\83à¸\8aà¹\89à¸\81ารà¹\81สà¸\94à¸\87à¸\95ัวอยà¹\88าà¸\87à¹\81à¸\9aà¸\9aสà¸\94",
        "tog-forceeditsummary": "เตือนเมื่อช่องคำอธิบายอย่างย่อว่าง",
        "tog-watchlisthideown": "ซ่อนการแก้ไขของฉันจากรายการเฝ้าดู",
        "tog-watchlisthidebots": "ซ่อนการแก้ไขของบอตจากรายการเฝ้าดู",
        "anoneditwarning": "<strong>คำเตือน:</strong> คุณมิได้ล็อกอิน สาธารณะจะเห็นเลขที่อยู่ไอพีของคุณหากคุณแก้ไข หากคุณ<strong>[$1 ล็อกอิน]</strong>หรือ<strong>[$2 สร้างบัญชี]</strong> การแก้ไขของคุณจะถือว่าเป็นของชื่อผู้ใช้ของคุณ ร่วมกับประโยชน์อื่น",
        "anonpreviewwarning": "<em>คุณมิได้ล็อกอิน การบันทึกจะเก็บเลขที่อยู่ไอพีของคุณในประวัติการแก้ไขของหน้านี้</em>",
        "missingsummary": "<strong>อย่าลืม:</strong> คุณยังไม่ได้ให้คำอธิบายการแก้ไข \nถ้าคุณคลิก \"{{int:savearticle}}\" อีก จะบันทึกการแก้ไขของคุณโดยไม่มีคำอธิบายการแก้ไข",
+       "selfredirect": "<strong>คำเตือน:</strong> คุณกำลังสร้างการเปลี่ยนทางไปบทความเดียวกัน หากคุณคลิก \"{{int:savearticle}}\" อีกครั้ง จะสร้างการเปลี่ยนทาง",
        "missingcommenttext": "กรุณากรอกความเห็นด้านล่าง",
        "missingcommentheader": "<strong>อย่าลืม:</strong> คุณยังไม่ได้ใส่หัวข้อ/พาดหัวสำหรับความเห็นนี้ \nถ้าคุณคลิก \"{{int:savearticle}}\" อีก จะบันทึกการแก้ไขของคุณโดยไม่มีหัวข้อ/พาดหัว",
        "summary-preview": "ตัวอย่างคำอธิบาย:",
index 13f4b01..742f39d 100644 (file)
        "anoneditwarning": "<strong>警告:</strong>您没有登录。您做出任何编辑后您的IP地址会公开可见。如果您<strong>[$1 登陆]</strong>或<strong>[$2 注册]</strong>一个账户,您的编辑将归属于您的用户名,以及有其他好处。",
        "anonpreviewwarning": "<em>你没有登录。保存会记录你的IP地址于该页面的编辑历史中。</em>",
        "missingsummary": "'''提示:'''你没有提供编辑摘要。如果你再次点击“{{int:savearticle}}”,你的编辑将不带编辑摘要保存。",
+       "selfredirect": "<strong>警告:</strong>您正在创建重定向到同一条目的重定向。\n如果您再次点击“{{int:savearticle}}”,重定向将被创建。",
        "missingcommenttext": "请在下面输入评论。",
        "missingcommentheader": "'''提示:''' 您还没有为此评论提供一个标题。如果您再次点击“{{int:savearticle}}”,您的编辑将不带标题保存。",
        "summary-preview": "摘要预览:",
        "protectlogtext": "下面是页面保护更改的列表。请见[[Special:ProtectedPages|受保护页面列表]]查看目前正在进行的页面保护的列表。",
        "protectedarticle": "保护“[[$1]]”",
        "modifiedarticleprotection": "更改“[[$1]]”的保护等级",
-       "unprotectedarticle": "移除保护自“[[$1]]”",
+       "unprotectedarticle": "移除页面“[[$1]]”的保护",
        "movedarticleprotection": "移动保护设置自“[[$2]]”至“[[$1]]”",
        "protect-title": "更改“$1”的保护等级",
        "protect-title-notallowed": "查看“$1”的保护等级",
        "confirm-purge-top": "要清除此页面的缓存吗?",
        "confirm-purge-bottom": "清除页面数据会清除缓存并强制显示最近的版本。",
        "confirm-watch-button": "确定",
-       "confirm-watch-top": "将此页添加到您的监视吗?",
+       "confirm-watch-top": "å°\86此页添å\8a å\88°æ\82¨ç\9a\84ç\9b\91è§\86å\88\97表å\90\97ï¼\9f",
        "confirm-unwatch-button": "确定",
        "confirm-unwatch-top": "从监视列表中删除此页吗?",
        "semicolon-separator": ";",
        "api-error-stashnosuchfilekey": "您试图在藏匿处访问的文件密钥不存在。",
        "api-error-timeout": "服务器没有在预期内响应。",
        "api-error-unclassified": "出现未知错误。",
-       "api-error-unknown-code": "未知错误:$1",
+       "api-error-unknown-code": "未知错误:“$1”。",
        "api-error-unknown-error": "内部错误:尝试上传文件时出错。",
        "api-error-unknown-warning": "未知的警告:“$1”。",
        "api-error-unknownerror": "未知错误:$1。",
index 93e0ea5..c11d392 100644 (file)
@@ -86,7 +86,7 @@
        "tog-shownumberswatching": "顯示正在監視的使用者數",
        "tog-oldsig": "現有簽名:",
        "tog-fancysig": "將簽名視為 Wikitext 語言 (不自動產生連結)",
-       "tog-uselivepreview": "使用即時預覽 (實驗中)",
+       "tog-uselivepreview": "使用即時預覽",
        "tog-forceeditsummary": "未填寫編輯摘要時提示我",
        "tog-watchlisthideown": "隱藏監視清單中我的編輯",
        "tog-watchlisthidebots": "隱藏監視清單中機器人的編輯",
        "generic-pool-error": "抱歉,太多使用者正嘗試檢視此資源,伺服器超出負荷。\n請稍候片刻再嘗試。",
        "pool-timeout": "正在等待取消鎖定",
        "pool-queuefull": "程序序列已滿",
-       "pool-errorunknown": "未知錯誤",
+       "pool-errorunknown": "不明錯誤",
        "pool-servererror": "無法使用程序計數服務 ($1)。",
        "aboutsite": "關於 {{SITENAME}}",
        "aboutpage": "Project:About",
        "anoneditwarning": "<strong>警告:</strong>您尚未登入。 若您進行任何的編輯您的 IP 位置將會被公開。 若您 <strong>[$1 登入]</strong> 或 <strong>[$2 建立帳號]</strong>,您的編輯將會以您的使用者名稱標示,擁有其他優點。",
        "anonpreviewwarning": "<em>您尚未登入。儲存頁面會將您的 IP 位址記錄在此頁面的編輯歷史中。</em>",
        "missingsummary": "<strong>提醒:</strong>您未填寫編輯摘要。\n若您再點選 \"{{int:savearticle}}\" 一次,將略過摘要直接儲存您的編輯。",
+       "selfredirect": "<strong>警告:</strong> 您正建立連結至自己的重新導向。\n若您再點選 \"{{int:savearticle}}\" 一次,將會繼續建立重新導向。",
        "missingcommenttext": "請在下方輸入評論。",
        "missingcommentheader": "<strong>提醒:</strong>您未填寫此評論的主旨/標題。\n若您再點選 \"{{int:savearticle}}\" 一次,將略過主旨/標題直接儲存您的評論。",
        "summary-preview": "摘要預覽:",
        "semiprotectedpagewarning": "<strong>注意:</strong>本頁已經被保護,只有已註冊的使用者才可編輯。\n以下提供最近的日誌以便參考:",
        "cascadeprotectedwarning": "<strong>警告:</strong>本頁已經被保護,只有擁有管理員權限的使用者才可編輯,此頁面被下列頁面引用因此連鎖保護:",
        "titleprotectedwarning": "<strong>警告:本頁面已被保護,需要 [[Special:ListGroupRights|特殊權限]] 方可建立。</strong>\n以下提供最近的日誌以便參考:",
-       "templatesused": "此頁面使用了以下{{PLURAL:$1|樣}}:",
+       "templatesused": "此頁面使用了以下{{PLURAL:$1|樣}}:",
        "templatesusedpreview": "此預覽使用了以下{{PLURAL:$1|樣板}}:",
-       "templatesusedsection": "此頁面使用了以下{{PLURAL:$1|樣}}:",
+       "templatesusedsection": "此頁面使用了以下{{PLURAL:$1|樣}}:",
        "template-protected": "(受保護)",
        "template-semiprotected": "(受半保護)",
        "hiddencategories": "此頁面屬於 {{PLURAL:$1|1 個隱藏分類|$1 個隱藏分類}}的成員:",
        "content-model-text": "純文字",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
-       "duplicate-args-category": "樣呼叫時使用重複的參數的頁面",
-       "duplicate-args-category-desc": "該頁面包含重複使用參數的樣呼叫,如 <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> 或 <code><nowiki>{{foo|bar|1=baz}}</nowiki>。",
+       "duplicate-args-category": "樣呼叫時使用重複的參數的頁面",
+       "duplicate-args-category-desc": "該頁面包含重複使用參數的樣呼叫,如 <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> 或 <code><nowiki>{{foo|bar|1=baz}}</nowiki>。",
        "expensive-parserfunction-warning": "<strong>警告:</strong>此頁面使用了太多消耗系統資源的解析函數。\n\n使用次數應小於 $2 次,但目前使用了 $1 次。",
        "expensive-parserfunction-category": "使用了太多消耗系統資源的分析函數的頁面",
        "post-expand-template-inclusion-warning": "<strong>警告:</strong>引用樣板後大小超出限制。\n部份樣板內容將不會被使用。",
        "post-expand-template-inclusion-category": "引用樣板後大小超出限制的頁面",
-       "post-expand-template-argument-warning": "<strong>警告:</strong>此頁面有一個以上的樣參數過長。\n過長的參數會被直接忽略。",
+       "post-expand-template-argument-warning": "<strong>警告:</strong>此頁面有一個以上的樣參數過長。\n過長的參數會被直接忽略。",
        "post-expand-template-argument-category": "樣板參數有部份被忽略的頁面",
        "parser-template-loop-warning": "偵測到樣板遞迴:[[$1]]",
-       "parser-template-recursion-depth-warning": "超出樣遞迴深度限制 ($1)",
+       "parser-template-recursion-depth-warning": "超出樣遞迴深度限制 ($1)",
        "language-converter-depth-warning": "已超出語言轉換器深度限制 ($1)",
        "node-count-exceeded-category": "節點數量超出限制的頁面",
        "node-count-exceeded-category-desc": "超出節點數量限制的頁面。",
        "history-feed-empty": "請求的頁面不存在,\n可能已被刪除或重新命名。\n請嘗試 [[Special:Search|搜尋本站]] 取得其他相關的新頁面。",
        "rev-deleted-comment": "(已移除編輯摘要)",
        "rev-deleted-user": " (已移除使用者名稱)",
-       "rev-deleted-event": "(已移除日誌)",
+       "rev-deleted-event": "(已移除日誌操作)",
        "rev-deleted-user-contribs": "[使用者名稱或 IP 位址已移除 - 已隱藏貢獻清單中的編輯]",
        "rev-deleted-text-permission": "此頁面修訂已被 <strong>刪除</strong>。\n可至 [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 刪除日誌] 取得詳細資訊。",
        "rev-suppressed-text-permission": "此頁面修訂已被 <strong>禁止顯示</strong>。\n可至 [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} 禁止顯示日誌] 取得詳細資訊。",
        "searchprofile-advanced-tooltip": "搜尋自訂命名空間",
        "search-result-size": "$1 ($2 個字)",
        "search-result-category-size": "$1 位成員 ($2 個子分類,$3 個檔案)",
-       "search-redirect": "(重新導向自 $1 )",
+       "search-redirect": " (重新導向自 $1 )",
        "search-section": "(章節 $1)",
        "search-category": "(分類 $1)",
        "search-file-match": "(符合檔案內容)",
        "listduplicatedfiles-summary": "此清單中包含最新版本的檔案與其他檔案重複的清單,本清單只顯示本地檔案。",
        "listduplicatedfiles-entry": "[[:File:$1|$1]] 有[[$3|其他 $2 個重複檔案]]。",
        "unusedtemplates": "未使用的樣板",
-       "unusedtemplatestext": "此頁面列出所有於 {{ns:template}} 命名空間下未被其他頁面引用的樣版。\n在刪除前,仍需檢查是否有連結這些樣版的其他頁面。",
+       "unusedtemplatestext": "此頁面列出所有於 {{ns:template}} 命名空間下未被其他頁面引用的樣板。\n在刪除前,仍需檢查是否有連結這些樣板的其他頁面。",
        "unusedtemplateswlh": "其他連結",
        "randompage": "隨機頁面",
        "randompage-nopages": "在{{PLURAL:$2|命名空間}}中沒有任何頁面:$1。",
        "uncategorizedpages": "未分類的頁面",
        "uncategorizedcategories": "未分類的分類",
        "uncategorizedimages": "未分類的檔案",
-       "uncategorizedtemplates": "待分類樣",
+       "uncategorizedtemplates": "待分類樣",
        "unusedcategories": "未使用的分類",
        "unusedimages": "未使用的檔案",
        "wantedcategories": "需要的分類",
        "wantedfiletext-cat-noforeign": "下列檔案已被使用但不存在。 除此之外,頁面已內嵌但不存在的檔案列於 [[:$1]]。",
        "wantedfiletext-nocat": "下列檔案被時用,但檔案不存在。 外部儲存庫的檔案儘管存在,但此清單仍會列出。 這類誤報的項目會以 <del>刪除線</del> 標示。",
        "wantedfiletext-nocat-noforeign": "下列檔案已被使用但不存在。",
-       "wantedtemplates": "需要的樣",
+       "wantedtemplates": "需要的樣",
        "mostlinked": "被連結最多的頁面",
        "mostlinkedcategories": "被連結最多的分類",
        "mostlinkedtemplates": "被引用最多的頁面",
        "trackingcategories-desc": "分類收錄標準",
        "noindex-category-desc": "命名空間允許,且含有魔術字 <code><nowiki>__NOINDEX__</nowiki></code> 未被機器人列入索引的頁面。",
        "index-category-desc": "命名空間允許,且含有魔術字 <code><nowiki>__INDEX__</nowiki></code> 被機器人列入索引的頁面。",
-       "post-expand-template-inclusion-category-desc": "展開樣版後大小超過 <code>$wgMaxArticleSize</code> 導致部份樣版未正常展開的頁面。",
-       "post-expand-template-argument-category-desc": "展開樣參數後大小超過 <code>$wgMaxArticleSize</code> 的頁面 (有些於三括號中,如 <code>{{{Foo}}}</code>)。",
+       "post-expand-template-inclusion-category-desc": "展開樣板後大小超過 <code>$wgMaxArticleSize</code> 導致部份樣板未正常展開的頁面。",
+       "post-expand-template-argument-category-desc": "展開樣參數後大小超過 <code>$wgMaxArticleSize</code> 的頁面 (有些於三括號中,如 <code>{{{Foo}}}</code>)。",
        "expensive-parserfunction-category-desc": "頁面使用太多消耗系統資源的解析器函數 (如 <code>#ifexist</code>)。\n請參考 [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit]。",
        "broken-file-category-desc": "含有損壞檔案連結的頁面 (內嵌檔案連結的檔案不存在)。",
        "hidden-category-category-desc": "內容中使用 <code><nowiki>__HIDDENCAT__</nowiki></code> 的分類,可隱藏預設在頁面上顯示的分類連結方塊。",
        "whatlinkshere-prev": "前 $1 筆",
        "whatlinkshere-next": "後 $1 筆",
        "whatlinkshere-links": "← 連結",
-       "whatlinkshere-hideredirs": "$1重新導向頁面",
+       "whatlinkshere-hideredirs": "$1 重新導向頁面",
        "whatlinkshere-hidetrans": "$1 引用",
        "whatlinkshere-hidelinks": "$1 連結",
        "whatlinkshere-hideimages": "$1 檔案連結",
        "tooltip-search": "搜尋 {{SITENAME}}",
        "tooltip-search-go": "若與此名稱相符的頁面存在,前往該頁面",
        "tooltip-search-fulltext": "搜尋使用此文字的頁面",
-       "tooltip-p-logo": "前往主頁",
-       "tooltip-n-mainpage": "前往主頁",
-       "tooltip-n-mainpage-description": "前往主頁",
+       "tooltip-p-logo": "前往主頁",
+       "tooltip-n-mainpage": "前往主頁",
+       "tooltip-n-mainpage-description": "前往主頁",
        "tooltip-n-portal": "關於本專案、您可以做什麼、哪裡可以找到您需要的事物",
        "tooltip-n-currentevents": "於最新動態中尋找背景資訊",
        "tooltip-n-recentchanges": "列出此 Wiki 中的近期變更清單",
        "pageinfo-recent-authors": "最近作者數",
        "pageinfo-magic-words": "魔術{{PLURAL:$1|字}} ($1)",
        "pageinfo-hidden-categories": "隱藏分類 ($1)",
-       "pageinfo-templates": "引用樣 ($1)",
+       "pageinfo-templates": "引用樣 ($1)",
        "pageinfo-transclusions": "頁面被引用於 ($1)",
        "pageinfo-toolboxlink": "頁面資訊",
        "pageinfo-redirectsto": "重新導向至",
        "exif-datetimemetadata": "資料定義最後修改日期",
        "exif-nickname": "非正式的影像名稱",
        "exif-rating": "評分 (共 5 分)",
-       "exif-rightscertificate": "版權管理證書",
+       "exif-rightscertificate": "版權管理憑證",
        "exif-copyrighted": "版權狀態",
        "exif-copyrightowner": "版權所有人",
        "exif-usageterms": "使用條款",
        "api-error-overwrite": "不允許覆蓋已存在的檔案。",
        "api-error-stashfailed": "內部錯誤:伺服器儲存暫存檔案失敗。",
        "api-error-publishfailed": "內部錯誤:伺服器發佈暫存檔案失敗。",
-       "api-error-stasherror": "上傳檔案至儲庫時發生錯誤。",
-       "api-error-stashedfilenotfound": "嘗試從藏匿處上傳時找不到藏匿的檔案。",
-       "api-error-stashpathinvalid": "æ\89¾å\88°ç\9a\84è\97\8få\8c¿æª\94æ¡\88ç\9a\84è·¯å¾\91æ\98¯ç\84¡æ\95\88ç\9a\84。",
-       "api-error-stashfilestorage": "儲存檔案至藏匿處時出錯。",
-       "api-error-stashzerolength": "伺服器不能藏匿檔案,因爲它已經沒有藏匿空間了。",
-       "api-error-stashnotloggedin": "您必須登入以儲存檔案至上傳藏匿處。",
-       "api-error-stashwrongowner": "您嘗試在藏匿處存取的檔案不屬於您。",
-       "api-error-stashnosuchfilekey": "您嘗試在藏匿處存取的檔案金鑰不存在。",
+       "api-error-stasherror": "上傳檔案至儲庫時發生錯誤。",
+       "api-error-stashedfilenotfound": "嘗試從儲藏庫上傳檔案時查無該檔案。",
+       "api-error-stashpathinvalid": "æ\87\89該å­\98å\9c¨å\84²è\97\8fæª\94æ¡\88ç\9a\84è·¯å¾\91ç\84¡æ\95\88。",
+       "api-error-stashfilestorage": "儲存檔案至儲藏庫時發生錯誤。",
+       "api-error-stashzerolength": "伺服器無法儲藏該檔案,因為該檔案大小為 0。",
+       "api-error-stashnotloggedin": "您必須登入以儲存檔案於上傳儲藏庫。",
+       "api-error-stashwrongowner": "您嘗試在儲藏庫存取的檔案不屬於您的。",
+       "api-error-stashnosuchfilekey": "您嘗試在儲藏庫存取的檔案金鑰不存在。",
        "api-error-timeout": "伺服器沒有在預期的時間內回應。",
        "api-error-unclassified": "發生不明錯誤。",
        "api-error-unknown-code": "不明錯誤:\"$1\"。",
        "limitreport-expansiondepth": "最高展開深度",
        "limitreport-expensivefunctioncount": "高消耗解析器函數次數",
        "expandtemplates": "展開樣板",
-       "expand_templates_intro": "本特殊頁面會將文字中的樣展開,可以包含支援的解析器語法,如 <code><nowiki>{{</nowiki>#language:…}}</code> 與變數如 <code><nowiki>{{</nowiki>CURRENTDAY}}</code>。\n實際上,絕大部分在雙括號中的內容都會被展開。",
+       "expand_templates_intro": "本特殊頁面會將文字中的樣展開,可以包含支援的解析器語法,如 <code><nowiki>{{</nowiki>#language:…}}</code> 與變數如 <code><nowiki>{{</nowiki>CURRENTDAY}}</code>。\n實際上,絕大部分在雙括號中的內容都會被展開。",
        "expand_templates_title": "上下文標題,用於 {{FULLPAGENAME}} 等:",
        "expand_templates_input": "輸入文字:",
        "expand_templates_output": "結果",
index 0852f44..3c99df0 100644 (file)
@@ -80,6 +80,7 @@ $specialPageAliases = array(
        'Listgrouprights'           => array( 'רשימת_הרשאות_לקבוצה' ),
        'Listredirects'             => array( 'רשימת_הפניות', 'הפניות' ),
        'Listusers'                 => array( 'רשימת_משתמשים', 'משתמשים' ),
+       'ListDuplicatedFiles'       => array( 'רשימת_קבצים_כפולים' ),
        'Lockdb'                    => array( 'נעילת_בסיס_הנתונים' ),
        'Log'                       => array( 'יומנים' ),
        'Lonelypages'               => array( 'דפים_יתומים' ),
@@ -122,6 +123,7 @@ $specialPageAliases = array(
        'Specialpages'              => array( 'דפים_מיוחדים' ),
        'Statistics'                => array( 'סטטיסטיקות' ),
        'Tags'                      => array( 'תגיות' ),
+       'TrackingCategories'        => array( 'קטגוריות_מעקב' ),
        'Unblock'                   => array( 'שחרור_חסימה' ),
        'Uncategorizedcategories'   => array( 'קטגוריות_חסרות_קטגוריה' ),
        'Uncategorizedimages'       => array( 'קבצים_חסרי_קטגוריה', 'תמונות_חסרות_קטגוריה' ),
index 1d558d2..3fda23a 100644 (file)
@@ -1184,7 +1184,7 @@ abstract class Maintenance {
         * We default as considering stdin a tty (for nice readline methods)
         * but treating stout as not a tty to avoid color codes
         *
-        * @param int $fd File descriptor
+        * @param mixed $fd File descriptor
         * @return bool
         */
        public static function posix_isatty( $fd ) {
index b97e1b0..2f533cf 100644 (file)
@@ -22,7 +22,6 @@
  */
 
 require_once __DIR__ . '/Maintenance.php';
-require_once 'PHPUnit/Autoload.php';
 
 /**
  * @ingroup Maintenance
@@ -43,6 +42,17 @@ class CheckLess extends Maintenance {
                // require it here.
                require_once __DIR__ . '/../tests/TestsAutoLoader.php';
 
+               // If phpunit isn't available by autoloader try pulling it in
+               if ( !class_exists( 'PHPUnit_Framework_TestCase' ) ) {
+                       require_once 'PHPUnit/Autoload.php';
+               }
+
+               // RequestContext::resetMain() will print warnings unless this
+               // is defined.
+               if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
+                       define( 'MW_PHPUNIT_TEST', true );
+               }
+
                $textUICommand = new PHPUnit_TextUI_Command();
                $argv = array(
                        "$IP/tests/phpunit/phpunit.php",
index 66e8da0..d17b06d 100644 (file)
@@ -91,6 +91,7 @@ class FindHooks extends Maintenance {
                        $IP . '/includes/jobqueue/',
                        $IP . '/includes/json/',
                        $IP . '/includes/logging/',
+                       $IP . '/includes/mail/',
                        $IP . '/includes/media/',
                        $IP . '/includes/page/',
                        $IP . '/includes/parser/',
index 910f56b..45cc339 100644 (file)
@@ -471,7 +471,7 @@ class RecompressTracked {
         * @param int $pageId
         */
        function doPage( $pageId ) {
-               $title = Title::newFromId( $pageId );
+               $title = Title::newFromID( $pageId );
                if ( $title ) {
                        $titleText = $title->getPrefixedText();
                } else {
index 470647a..55f535d 100644 (file)
@@ -37,12 +37,18 @@ class UpdateArticleCount extends Maintenance {
                parent::__construct();
                $this->mDescription = "Count of the number of articles and update the site statistics table";
                $this->addOption( 'update', 'Update the site_stats table with the new count' );
+               $this->addOption( 'use-master', 'Count using the master database' );
        }
 
        public function execute() {
                $this->output( "Counting articles..." );
 
-               $counter = new SiteStatsInit( false );
+               if ( $this->hasOption( 'use-master' ) ) {
+                       $dbr = wfGetDB( DB_MASTER );
+               } else {
+                       $dbr = wfGetDB( DB_SLAVE, 'vslow' );
+               }
+               $counter = new SiteStatsInit( $dbr );
                $result = $counter->articles();
 
                $this->output( "found {$result}.\n" );
index 1049a6a..1eda5d6 100644 (file)
@@ -758,6 +758,7 @@ return array(
                        'zh-cn' => 'resources/lib/moment/locale/zh-cn.js',
                        'zh-tw' => 'resources/lib/moment/locale/zh-tw.js',
                ),
+               'targets' => array( 'desktop', 'mobile' ),
        ),
 
        /* MediaWiki */
index 9972321..9b8a0ce 100644 (file)
@@ -3,10 +3,16 @@
  */
 ( function ( mw, $ ) {
        $( function () {
-               var api = new mw.Api(), pending = null, $form = $( '#editform' );
+               var idleTimeout = 5000,
+                       api = new mw.Api(),
+                       pending = null,
+                       $form = $( '#editform' ),
+                       $text = $form.find( '#wpTextbox1' ),
+                       data = {},
+                       timer = null;
 
                function stashEdit( token ) {
-                       var data = $form.serializeObject();
+                       data = $form.serializeObject();
 
                        pending = api.post( {
                                action: 'stashedit',
                        } );
                }
 
+               /* Has the edit body text changed since the last stashEdit() call? */
+               function isChanged() {
+                       // Normalize line endings to CRLF, like $.fn.serializeObject does.
+                       var newText = $text.val().replace( /\r?\n/g, '\r\n' );
+                       return newText !== data.wpTextbox1;
+               }
+
                function onEditChanged() {
-                       // If a stash request is already in flight, abort it, since its
-                       // payload has just been invalidated by this change.
+                       if ( !isChanged() ) {
+                               return;
+                       }
+
+                       // If a request is in progress, abort it; its payload is stale.
                        if ( pending ) {
                                pending.abort();
                        }
+
                        api.getToken( 'edit' ).then( stashEdit );
                }
 
+               function onKeyPress( e ) {
+                       // Ignore keystrokes that don't modify text, like cursor movements.
+                       // See <http://stackoverflow.com/q/2284844>.
+                       if ( e.which === 0 ) {
+                               return;
+                       }
+
+                       clearTimeout( timer );
+
+                       if ( pending ) {
+                               pending.abort();
+                       }
+
+                       timer = setTimeout( onEditChanged, idleTimeout );
+               }
+
                // We don't attempt to stash new section edits because in such cases
                // the parser output varies on the edit summary (since it determines
                // the new section's name).
@@ -37,6 +70,7 @@
                        return;
                }
 
-               $form.find( '#wpTextbox1' ).on( 'change', onEditChanged );
+               $text.on( { change: onEditChanged, keypress: onKeyPress } );
+
        } );
 }( mediaWiki, jQuery ) );
index 39129cb..5f19e8b 100644 (file)
@@ -16,7 +16,7 @@
 # cat           add category links
 # ill           add inter-language links
 # subpage       enable subpages (disabled by default)
-# noxml         don't check for XML well formdness
+# noxml         don't check for XML well-formedness
 # title=[[XXX]] run test using article title XXX
 # language=XXX  set content language to XXX for this test
 # variant=XXX   set the variant of language for this test (eg zh-tw)
@@ -538,7 +538,6 @@ Italics and bold: 2-quote opening sequence: (2,2)
 </p>
 !!end
 
-
 !! test
 Italics and bold: 2-quote opening sequence: (2,3)
 !! options
@@ -550,18 +549,16 @@ parsoid=wt2html
 </p>
 !!end
 
-
 # same html as previous, but wikitext adjusted to match parsoid html2wt
 !! test
 Italics and bold: 2-quote opening sequence: (2,3) w/ nowiki
 !! wikitext
-''<nowiki>foo'</nowiki>''
+''foo'<nowiki/>''
 !! html
 <p><i>foo'</i>
 </p>
 !! end
 
-
 !! test
 Italics and bold: 2-quote opening sequence: (2,4)
 !! options
@@ -573,18 +570,16 @@ parsoid=wt2html
 </p>
 !!end
 
-
 # same html as previous, but wikitext adjusted to match parsoid html2wt
 !! test
 Italics and bold: 2-quote opening sequence: (2,4) w/ nowiki
 !! wikitext
-''<nowiki>foo''</nowiki>''
+''foo<nowiki>''</nowiki>''
 !! html
 <p><i>foo''</i>
 </p>
 !! end
 
-
 # The PHP parser strips the empty tags out for giggles; parsoid doesn't.
 !! test
 Italics and bold: 2-quote opening sequence: (2,5)
@@ -620,13 +615,24 @@ Italics and bold: 2-quote opening sequence: (2,5+3) w/ nowiki
 
 !! test
 Italics and bold: 3-quote opening sequence: (3,2)
+!! options
+parsoid=wt2html
 !! wikitext
 '''foo''
-!! html
+!! html/*
 <p>'<i>foo</i>
 </p>
 !!end
 
+# same html as previous, but wikitext adjusted to match parsoid html2wt
+!! test
+Italics and bold: 3-quote opening sequence: (3,2) w/ nowiki
+!! wikitext
+'<nowiki/>''foo''
+!! html
+<p>'<i>foo</i>
+</p>
+!!end
 
 !! test
 Italics and bold: 3-quote opening sequence: (3,3)
@@ -637,7 +643,6 @@ Italics and bold: 3-quote opening sequence: (3,3)
 </p>
 !!end
 
-
 !! test
 Italics and bold: 3-quote opening sequence: (3,4)
 !! options
@@ -649,18 +654,16 @@ parsoid=wt2html
 </p>
 !!end
 
-
 # same html as previous, but wikitext adjusted to match parsoid html2wt
 !! test
 Italics and bold: 3-quote opening sequence: (3,4) w/ nowiki
 !! wikitext
-'''<nowiki>foo'</nowiki>'''
+'''foo'<nowiki/>'''
 !! html
 <p><b>foo'</b>
 </p>
 !! end
 
-
 # The PHP parser strips the empty tags out for giggles; parsoid doesn't.
 !! test
 Italics and bold: 3-quote opening sequence: (3,5)
@@ -705,7 +708,6 @@ parsoid=wt2html
 </p>
 !!end
 
-
 # same html as previous, but wikitext adjusted to match parsoid html2wt
 !! test
 Italics and bold: 4-quote opening sequence: (4,2) w/ nowiki
@@ -716,16 +718,26 @@ Italics and bold: 4-quote opening sequence: (4,2) w/ nowiki
 </p>
 !! end
 
-
 !! test
 Italics and bold: 4-quote opening sequence: (4,3)
+!! options
+parsoid=wt2html
 !! wikitext
 ''''foo'''
-!! html
+!! html/*
 <p>'<b>foo</b>
 </p>
 !!end
 
+# same html as previous, but wikitext adjusted to match parsoid html2wt
+!! test
+Italics and bold: 4-quote opening sequence: (4,3) w/ nowiki
+!! wikitext
+'<nowiki/>'''foo'''
+!! html
+<p>'<b>foo</b>
+</p>
+!!end
 
 !! test
 Italics and bold: 4-quote opening sequence: (4,4)
@@ -738,18 +750,16 @@ parsoid=wt2html
 </p>
 !!end
 
-
 # same html as previous, but wikitext adjusted to match parsoid html2wt
 !! test
 Italics and bold: 4-quote opening sequence: (4,4) w/ nowiki
 !! wikitext
-''''<nowiki>foo'</nowiki>'''
+'<nowiki/>'''foo'<nowiki/>'''
 !! html
 <p>'<b>foo'</b>
 </p>
 !! end
 
-
 # The PHP parser strips the empty tags out for giggles; parsoid doesn't.
 !! test
 Italics and bold: 4-quote opening sequence: (4,5)
@@ -769,7 +779,7 @@ parsoid=wt2html
 !! test
 Italics and bold: 4-quote opening sequence: (4,5+2) w/ nowiki
 !! wikitext
-''''foo'''''<nowiki/>''
+'<nowiki/>'''foo'''''<nowiki/>''
 !! html/php
 <p>'<b>foo</b>
 </p>
@@ -794,7 +804,6 @@ parsoid=wt2html
 </p>
 !!end
 
-
 # same html as previous, but wikitext adjusted to match parsoid html2wt
 # skipping wt2html and html2html because it wants to put <i> before <b>
 !! test
@@ -819,7 +828,6 @@ parsoid=wt2html
 </p>
 !!end
 
-
 # same html as previous, but wikitext adjusted to match parsoid html2wt
 !! test
 Italics and bold: 5-quote opening sequence: (5,3+2)
@@ -830,7 +838,6 @@ Italics and bold: 5-quote opening sequence: (5,3+2)
 </p>
 !! end
 
-
 !! test
 Italics and bold: 5-quote opening sequence: (5,4)
 !! options
@@ -842,18 +849,16 @@ parsoid=wt2html
 </p>
 !!end
 
-
 # same html as previous, but wikitext adjusted to match parsoid html2wt
 !! test
 Italics and bold: 5-quote opening sequence: (5,4+2) w/ nowiki
 !! wikitext
-'''''<nowiki>foo'</nowiki>'''''
+'''''foo'<nowiki/>'''''
 !! html
 <p><i><b>foo'</b></i>
 </p>
 !! end
 
-
 !! test
 Italics and bold: 5-quote opening sequence: (5,5)
 !! wikitext
@@ -882,7 +887,7 @@ parsoid=wt2html
 !! test
 Italics and bold: multiple quote sequences: (2,4,2+3) w/ nowiki
 !! wikitext
-''<nowiki>foo'</nowiki>'''bar'''''
+''foo'<nowiki/>'''bar'''''
 !! html
 <p><i>foo'<b>bar</b></i>
 </p>
@@ -905,7 +910,7 @@ parsoid=wt2html
 !! test
 Italics and bold: multiple quote sequences: (2,4,3+2) w/ nowiki
 !! wikitext
-''<nowiki>foo'</nowiki>'''bar'''''
+''foo'<nowiki/>'''bar'''''
 !! html
 <p><i>foo'<b>bar</b></i>
 </p>
@@ -928,7 +933,7 @@ parsoid=wt2html
 !! test
 Italics and bold: multiple quote sequences: (2,4,4+2) w/ nowiki
 !! wikitext
-''<nowiki>foo'</nowiki>'''<nowiki>bar'</nowiki>'''''
+''foo'<nowiki/>'''bar'<nowiki/>'''''
 !! html
 <p><i>foo'<b>bar'</b></i>
 </p>
@@ -1030,14 +1035,11 @@ parsoid=wt2html
 
 
 # same html as previous, but wikitext adjusted to match parsoid html2wt
-# add 'parsoid' option to use 'parsoid' normalization of the placeholder
 !! test
 Italics and bold: other quote tests: (3,2,3+2+2,2)
-!! options
-parsoid
 !! wikitext
 '''this is about ''foo'''''<nowiki/>''s family''
-!! html/*
+!! html
 <p><b>this is about <i>foo</i></b><i>s family</i>
 </p>
 !! end
@@ -1046,8 +1048,20 @@ parsoid
 !! test
 Italics and bold: other quote tests: (3,2,3,3)
 !! options
+parsoid=wt2html
 !! wikitext
 '''this is about ''foo'''s family'''
+!! html/*
+<p>'<i>this is about </i>foo<b>s family</b>
+</p>
+!!end
+
+
+# same html as previous, but wikitext adjusted to match parsoid html2wt
+!! test
+Italics and bold: other quote tests: (3,2,3,3) w/ nowiki
+!! wikitext
+'<nowiki/>''this is about ''foo'''s family'''
 !! html
 <p>'<i>this is about </i>foo<b>s family</b>
 </p>
@@ -1776,7 +1790,7 @@ b</div>
 ## of eager output of buffered tokens in the p-wrapper. But, I'm going to ignore
 ## them for now.
 !! test
-P-wrapping should leave sol-transparent tags outside p-tags where possible
+1. P-wrapping should leave sol-transparent tags outside p-tags where possible
 !! options
 parsoid=wt2html
 !! wikitext
@@ -1788,6 +1802,16 @@ a [[Category:A1]] [[Category:A2]]
 <link href="Category:A1"/> <link href="Category:A2"/> <link href="Category:A3"/> <link href="Category:A4"/>
 !! end
 
+!! test
+2. P-wrapping should leave sol-transparent tags outside p-tags where possible
+!! options
+parsoid=wt2html
+!! wikitext
+[[Category:A1]]a
+!! html/parsoid
+<link href="Category:A1"/><p>a</p>
+!! end
+
 ###
 ### Preformatted text
 ###
@@ -2244,7 +2268,8 @@ parsoid=wt2html
 <table><pre></pre></table>
 
 !! html/parsoid
-<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;pre &lt;pre>x&lt;/pre>"}},"i":0}}]}'>&lt;pre </p><pre>x</pre>
+<pre about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"a":{"&lt;pre":null},"sa":{"&lt;pre":""},"stx":"html","pi":[[{"k":"1","spc":["","","",""]}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;pre &lt;pre>x&lt;/pre>"}},"i":0}}]}'>x</pre>
+
 
 <p>&lt;pre </p>
 
@@ -2423,6 +2448,41 @@ Templates: Handle comments in the target
 <p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo"}},"i":0}}]}'>foo</p>
 !!end
 
+!! test
+Templates: Handle comments in parameter names (bug 67657)
+!! wikitext
+{{echo|1
+<!-- should be ignored -->
+=foo}}
+
+{{echo|
+<!-- should be ignored -->
+1 = foo}}
+
+{{echo|1<!-- should be ignored --> = foo}}
+
+{{echo|<!-- should be ignored -->1 = foo}}
+!!html/parsoid
+<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo","key":{"wt":"1\n&lt;!-- should be ignored -->"}}},"i":0}}]}'>foo</p>
+
+<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo","key":{"wt":"&lt;!-- should be ignored -->\n1"}}},"i":0}}]}'>foo</p>
+
+<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo","key":{"wt":"1&lt;!-- should be ignored -->"}}},"i":0}}]}'>foo</p>
+
+<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo","key":{"wt":"&lt;!-- should be ignored -->1"}}},"i":0}}]}'>foo</p>
+!!end
+
+!! test
+Templates: Other wikitext in parameter names (bug 67657)
+!! wikitext
+{{echo|''1''=foo}}
+!!html/parsoid
+<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"&#39;&#39;1&#39;&#39;":{"wt":"foo"}},"i":0}}]}'>{{{1}}}</p>
+!!html/php
+<p>{{{1}}}
+</p>
+!!end
+
 #--------------------------------------------------------------------
 # Transclusion parameter escaping tests
 #--------------------------------------------------------------------
@@ -4099,6 +4159,46 @@ External links: with no contents
 <p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" title="wikipedia:Foo"><span>Bar</span></a></p>
 !! end
 
+!! test
+External links: Free with trailing punctuation
+!! wikitext
+http://example.com,
+http://example.com;
+http://example.com\
+http://example.com.
+http://example.com:
+http://example.com!
+http://example.com?
+http://example.com)
+http://example.com/url_with_(brackets)
+!! html
+<p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>,
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>;
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>\
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>.
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>:
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>!
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>?
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>)
+<a rel="nofollow" class="external free" href="http://example.com/url_with_(brackets)">http://example.com/url_with_(brackets)</a>
+</p>
+!! end
+
+!! test
+External links: No preceding word characters allowed (bug 65278)
+!! wikitext
+NOPEhttp://example.com
+N0http://example.com
+ok:http://example.com
+ok-http://example.com
+!! html
+<p>NOPEhttp://example.com
+N0http://example.com
+ok:<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>
+ok-<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>
+</p>
+!! end
+
 !! test
 External image
 !! wikitext
@@ -5440,6 +5540,9 @@ Template-generated table cell attributes and cell content
 {|
 |{{table_attribs}}
 | {{table_attribs}}
+| <!--foo--> <!--bar--> <!--baz--> {{table_attribs}}
+|align=center {{table_attribs}}
+| <!--foo--> align=center <!--bar--> {{table_attribs}}
 |}
 !! html
 <table>
@@ -5447,26 +5550,18 @@ Template-generated table cell attributes and cell content
 <td style="color: red"> Foo
 </td>
 <td style="color: red"> Foo
-</td></tr></table>
-
-!! end
-
-!! test
-Template-generated table cell attributes and cell content (2)
-!! wikitext
-{|
-|align=center {{table_attribs}}
-|}
-!! html
-<table>
-<tr>
+</td>
+<td style="color: red"> Foo
+</td>
+<td align="center" style="color: red"> Foo
+</td>
 <td align="center" style="color: red"> Foo
 </td></tr></table>
 
 !! end
 
 !! test
-Template-generated table cell attributes and cell content (3)
+Template-generated table cell attributes and cell content (2)
 !! wikitext
 {|
 |align=center {{table_cells}}
@@ -5639,6 +5734,68 @@ Build table with {{!}}
 
 !! end
 
+!! test
+Build table with pipe as data
+!! wikitext
+{| class="wikitable"
+! header
+! second header
+|- style="color:red;"
+| data || style="color:red;" | second data
+|-
+| style="color:red;" | data with | || style="color:red;" | second data with |
+|-
+|| data with | ||| second data with |
+|}
+!! html
+<table class="wikitable">
+<tr>
+<th> header
+</th>
+<th> second header
+</th></tr>
+<tr style="color:red;">
+<td> data </td>
+<td style="color:red;"> second data
+</td></tr>
+<tr>
+<td style="color:red;"> data with | </td>
+<td style="color:red;"> second data with |
+</td></tr>
+<tr>
+<td> data with | </td>
+<td> second data with |
+</td></tr></table>
+
+!! end
+
+!! test
+Build table with wikilink
+!! wikitext
+{| class="wikitable"
+! header || second header
+|- style="color:red;"
+| data [[Main Page|linktext]] || second data [[Main Page|linktext]]
+|-
+| data || second data [[Main Page|link|text with pipe]]
+|}
+!! html
+<table class="wikitable">
+<tr>
+<th> header </th>
+<th> second header
+</th></tr>
+<tr style="color:red;">
+<td> data <a href="/wiki/Main_Page" title="Main Page">linktext</a> </td>
+<td> second data <a href="/wiki/Main_Page" title="Main Page">linktext</a>
+</td></tr>
+<tr>
+<td> data </td>
+<td> second data <a href="/wiki/Main_Page" title="Main Page">link|text with pipe</a>
+</td></tr></table>
+
+!! end
+
 # The expected HTML structure in this test is debatable. The PHP parser does
 # not parse this kind of table at all. The main focus for Parsoid is on
 # round-tripping, so this output is ok for now. TODO: revisit!
@@ -6310,7 +6467,7 @@ Link containing double-single-quotes '' in text embedded in italics (bug 4598 sa
 !! test
 Link with double quotes in title part (literal) and alternate part (interpreted)
 !! wikitext
-[[File:Denys Savchenko ''Pentecoste''.jpg]]
+[[File:Denys_Savchenko_''Pentecoste''.jpg]]
 
 [[''Pentecoste'']]
 
@@ -6324,7 +6481,7 @@ Link with double quotes in title part (literal) and alternate part (interpreted)
 </p><p><a href="/index.php?title=%27%27Pentecoste%27%27&amp;action=edit&amp;redlink=1" class="new" title="''Pentecoste'' (page does not exist)"><i>Pentecoste</i></a>
 </p>
 !! html/parsoid
-<meta typeof="mw:Placeholder"/>
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="./File:Denys_Savchenko_''Pentecoste''.jpg"><img resource="./File:Denys_Savchenko_''Pentecoste''.jpg" src="./Special:FilePath/Denys_Savchenko_''Pentecoste''.jpg" height="220" width="220"/></a></span></p>
 <p><a rel="mw:WikiLink" href="''Pentecoste''" title="''Pentecoste''">''Pentecoste''</a></p>
 <p><a rel="mw:WikiLink" href="''Pentecoste''" title="''Pentecoste''">Pentecoste</a></p>
 <p><a rel="mw:WikiLink" href="''Pentecoste''" title="''Pentecoste''"><i>Pentecoste</i></a></p>
@@ -6334,15 +6491,20 @@ Link with double quotes in title part (literal) and alternate part (interpreted)
 Broken image links with HTML captions (bug 39700)
 !! wikitext
 [[File:Nonexistent|<script></script>]]
-[[File:Nonexistent|100px|<script></script>]]
+[[File:Nonexistent|100x100px|<script></script>]]
 [[File:Nonexistent|&lt;]]
 [[File:Nonexistent|a<i>b</i>c]]
-!! html
+!! html/php
 <p><a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;script&gt;&lt;/script&gt;</a>
 <a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;script&gt;&lt;/script&gt;</a>
 <a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;</a>
 <a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">abc</a>
 </p>
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"&lt;script>&lt;/script>"}'><a href="./File:Nonexistent"><img resource="./File:Nonexistent" src="./Special:FilePath/Nonexistent" height="220" width="220"/></a></span>
+<span typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"&lt;script>&lt;/script>"}'><a href="./File:Nonexistent" data-parsoid='{"a":{"href":"./File:Nonexistent"},"sa":{}}'><img resource="./File:Nonexistent" src="./Special:FilePath/Nonexistent" height="100" width="100"/></a></span>
+<span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"&amp;lt;"}'><a href="./File:Nonexistent"><img resource="./File:Nonexistent" src="./Special:FilePath/Nonexistent" height="220" width="220"/></a></span>
+<span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"a&lt;i>b&lt;/i>c"}'><a href="./File:Nonexistent"><img resource="./File:Nonexistent" src="./Special:FilePath/Nonexistent" height="220" width="220"/></a></span></p>
 !! end
 
 !! test
@@ -6916,6 +7078,8 @@ parsoid=wt2html,wt2wt,html2html
 
 !! test
 Interlanguage link
+!! options
+parsoid=wt2html,wt2wt,html2html
 !! wikitext
 Blah blah blah
 [[zh:Chinese]]
@@ -6944,6 +7108,8 @@ Blah blah blah
 
 !! test
 Double interlanguage link
+!! options
+parsoid=wt2html,wt2wt,html2html
 !! wikitext
 Blah blah blah
 [[es:Spanish]]
@@ -6959,17 +7125,23 @@ Blah blah blah
 
 !! test
 Interlanguage link variations
+!! options
+parsoid=wt2html,wt2wt,html2html
 !! wikitext
 Blah blah blah
 [[   es :Spanish]]
 [[ ZH :Chinese]]
+[[es:Foo_bar]]
+[[es:Foo bar]]
 !! html/php
 <p>Blah blah blah
 </p>
 !! html/parsoid
 <p>Blah blah blah</p>
-<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Spanish" data-parsoid='{"stx":"simple","a":{"href":"http://es.wikipedia.org/wiki/Spanish"},"sa":{"href":"   es :Spanish"}}'/>
-<link rel="mw:PageProp/Language" href="http://zh.wikipedia.org/wiki/Chinese" data-parsoid='{"stx":"simple","a":{"href":"http://zh.wikipedia.org/wiki/Chinese"},"sa":{"href":" ZH :Chinese"}}'/>
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Spanish" />
+<link rel="mw:PageProp/Language" href="http://zh.wikipedia.org/wiki/Chinese" />
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Foo_bar" />
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Foo_bar" />
 !! end
 
 !! test
@@ -7373,6 +7545,8 @@ Failing to transform badly formed HTML into correct XHTML
 </p>
 !!end
 
+## FIXME: Is Parsoid's acceptance of self-closing html-tags
+## a feature or a bug? See https://phabricator.wikimedia.org/T76962
 !! test
 Handling html with a div self-closing tag
 !! wikitext
@@ -7382,7 +7556,7 @@ Handling html with a div self-closing tag
 <div title=bar />
 <div title=bar/>
 <div title=bar/ >
-!! html
+!! html/php
 <p>&lt;div title /&gt;
 &lt;div title/&gt;
 </p>
@@ -7393,6 +7567,13 @@ Handling html with a div self-closing tag
 <div title="bar/"></div>
 </div>
 
+!! html/parsoid
+<div title="" data-parsoid='{"stx":"html","selfClose":true}'></div>
+<div title="" data-parsoid='{"stx":"html","selfClose":true}'></div>
+<div title="" data-parsoid='{"stx":"html","selfClose":true,"brokenHTMLTag":true}'></div>
+<div title="bar" data-parsoid='{"stx":"html","selfClose":true}'></div>
+<div title="bar" data-parsoid='{"stx":"html","selfClose":true}'></div>
+<div title="bar/" data-parsoid='{"stx":"html","autoInsertedEnd":true}'></div>
 !! end
 
 !! test
@@ -7415,7 +7596,7 @@ Handling html with a br self-closing tag
 !! html/parsoid
 <p><br title="" />
 <br title="" />
-<br />
+<br title="" />
 <br title="bar" />
 <br title="bar" />
 <br title="bar/" />
@@ -8720,6 +8901,15 @@ RFC 822
 </p>
 !! end
 
+!! test
+Magic links: RFC (bug 65278)
+!! wikitext
+This is RFC 822 but thisRFC 822 is not RFC 822linked.
+!! html
+<p>This is <a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc822">RFC 822</a> but thisRFC 822 is not RFC 822linked.
+</p>
+!! end
+
 !! test
 Magic links: ISBN (bug 1937)
 !! wikitext
@@ -8729,6 +8919,15 @@ ISBN 0-306-40615-2
 </p>
 !! end
 
+!! test
+Magic links: ISBN (bug 65278)
+!! wikitext
+This is ISBN 978-0-316-09811-3 but thisISBN 978-0-316-09811-3 is not ISBN 978-0-316-09811-3linked.
+!! html
+<p>This is <a href="/wiki/Special:BookSources/9780316098113" class="internal mw-magiclink-isbn">ISBN 978-0-316-09811-3</a> but thisISBN 978-0-316-09811-3 is not ISBN 978-0-316-09811-3linked.
+</p>
+!! end
+
 !! test
 Magic links: PMID incorrectly converts space to underscore
 !! wikitext
@@ -8738,6 +8937,15 @@ PMID 1234
 </p>
 !! end
 
+!! test
+Magic links: PMID (bug 65278)
+!! wikitext
+This is PMID 1234 but thisPMID 1234 is not PMID 1234linked.
+!! html
+<p>This is <a class="external mw-magiclink-pmid" rel="nofollow" href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract">PMID 1234</a> but thisPMID 1234 is not PMID 1234linked.
+</p>
+!! end
+
 ###
 ### Templates
 ####
@@ -8963,8 +9171,7 @@ Template with complex template as argument
 !! test
 Template with thumb image (with link in description)
 !! wikitext
-{{paramtest|
-  param =[[Image:noimage.png|thumb|[[no link|link]] [[no link|caption]]]]}}
+{{paramtest|param =[[Image:noimage.png|thumb|[[no link|link]] [[no link|caption]]]]}}
 !! html/php
 This is a test template with parameter <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&amp;wpDestFile=Noimage.png" class="new" title="File:Noimage.png">File:Noimage.png</a>  <div class="thumbcaption"><a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">link</a> <a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">caption</a></div></div></div>
 
@@ -8975,6 +9182,8 @@ This is a test template with parameter <div class="thumb tright"><div class="thu
 <div class="thumbcaption"><a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">link</a> <a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">caption</a></div>
 </div>
 </div>
+!! html/parsoid
+<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"paramtest","href":"./Template:Paramtest"},"params":{"param":{"wt":"[[Image:noimage.png|thumb|[[no link|link]] [[no link|caption]]]]"}},"i":0}}]}'>This is a test template with parameter </p><figure class="mw-default-size" typeof="mw:Error mw:Image/Thumb" about="#mwt1" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="./File:Noimage.png" ><img resource="./File:Noimage.png" src="./Special:FilePath/Noimage.png" height="220" width="220"/></a><figcaption><a rel="mw:WikiLink" href="./No_link" title="No link">link</a> <a rel="mw:WikiLink" href="./No_link" title="No link">caption</a></figcaption></figure>
 !! end
 
 !! article
@@ -12067,11 +12276,13 @@ File:Barfoo.jpg
 #REDIRECT [[File:Barfoo.jpg]]
 !! endarticle
 
+# FIXME: Parsoid should run this test -- but we'd need to teach the
+# mockAPI about the redirected Barfoo.jpg image.
 !! test
 Redirected image
 !! wikitext
 [[Image:Barfoo.jpg]]
-!! html
+!! html/php
 <p><a href="/wiki/File:Barfoo.jpg" title="File:Barfoo.jpg">File:Barfoo.jpg</a>
 </p>
 !! end
@@ -12081,10 +12292,12 @@ Missing image with uploads disabled
 !! options
 wgEnableUploads=0
 !! wikitext
-[[Image:Foobaz.jpg]]
-!! html
+[[File:Foobaz.jpg]]
+!! html/php
 <p><a href="/wiki/File:Foobaz.jpg" title="File:Foobaz.jpg">File:Foobaz.jpg</a>
 </p>
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="File:Foobaz.jpg"><img resource="./File:Foobaz.jpg" src="./Special:FilePath/Foobaz.jpg" height="220" width="220"/></a></span></p>
 !! end
 
 # Parsoid-specific testing for images
@@ -12323,7 +12536,12 @@ subpage title=[[Subpage test]]
 </p>
 !! end
 
-# TODO: make this PHP-parser compatible!
+!! article
+Subpage test/1/2/subpage
+!! text
+blah
+!! endarticle
+
 !! test
 Relative subpage noslash link
 !! options
@@ -12333,8 +12551,12 @@ subpage title=[[Subpage test/1/2/3/4]]
 [[../../subpage/]]
 
 [[../../subpage]]
-!! html
-<p><a rel="mw:WikiLink" href="Subpage_test/1/2/subpage/" title="Subpage test/1/2/subpage/">subpage</a></p>
+!! html/php
+<p><a href="/wiki/Subpage_test/1/2/subpage" title="Subpage test/1/2/subpage">subpage</a>
+</p><p><a href="/wiki/Subpage_test/1/2/subpage" title="Subpage test/1/2/subpage">Subpage test/1/2/subpage</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="Subpage_test/1/2/subpage" title="Subpage test/1/2/subpage">subpage</a></p>
 <p><a rel="mw:WikiLink" href="Subpage_test/1/2/subpage" title="Subpage test/1/2/subpage">Subpage_test/1/2/subpage</a></p>
 !! end
 
@@ -13671,19 +13893,23 @@ Media link to nonexistent file (bug 1702)
 !! test
 Image link to nonexistent file (bug 1850 - good)
 !! wikitext
-[[Image:No such.jpg]]
-!! html
+[[File:No_such.jpg]]
+!! html/php
 <p><a href="/index.php?title=Special:Upload&amp;wpDestFile=No_such.jpg" class="new" title="File:No such.jpg">File:No such.jpg</a>
 </p>
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="File:No_such.jpg"><img resource="./File:No_such.jpg" src="./Special:FilePath/No_such.jpg" height="220" width="220"/></a></span></p>
 !! end
 
 !! test
 :Image link to nonexistent file (bug 1850 - bad)
 !! wikitext
 [[:Image:No such.jpg]]
-!! html
+!! html/php
 <p><a href="/index.php?title=File:No_such.jpg&amp;action=edit&amp;redlink=1" class="new" title="File:No such.jpg (page does not exist)">Image:No such.jpg</a>
 </p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./File:No_such.jpg" title="File:No such.jpg">Image:No such.jpg</a></p>
 !! end
 
 
@@ -15042,7 +15268,7 @@ Fuzz testing: image with bogus manual thumbnail
 <div class="thumb tright"><div class="thumbinner" style="width:182px;">Error creating thumbnail:   <div class="thumbcaption"></div></div></div>
 
 !! html/parsoid
-<meta typeof="mw:Placeholder" data-parsoid='{"src":"[[Image:foobar.jpg|thumbnail= ]]","optList":[{"ck":"manualthumb","ak":"thumbnail= "}]}'/>
+<figure class="mw-default-size" typeof="mw:Error mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"manualthumb","ak":"thumbnail= "}],"dsr":[0,32,2,2]}' data-mw='{"errors":[{"key":"missing-thumbnail","message":"This thumbnail does not exist.","params":{"name":""}}],"thumb":""}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{},"dsr":[2,30,null,null]}'><img resource="./File:Foobar.jpg" src="./Special:FilePath/" height="220" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"220","width":"220"},"sa":{"resource":"Image:foobar.jpg"}}'/></a></figure>
 !!end
 
 !! test
@@ -16625,9 +16851,11 @@ Image with page parameter
 djvu
 !! wikitext
 [[File:LoremIpsum.djvu|page=2]]
-!! html
+!! html/php
 <p><a href="/index.php?title=File:LoremIpsum.djvu&amp;page=2" class="image"><img alt="LoremIpsum.djvu" src="http://example.com/images/thumb/5/5f/LoremIpsum.djvu/page2-2480px-LoremIpsum.djvu.jpg" width="2480" height="3508" srcset="http://example.com/images/thumb/5/5f/LoremIpsum.djvu/page2-3720px-LoremIpsum.djvu.jpg 1.5x, http://example.com/images/thumb/5/5f/LoremIpsum.djvu/page2-4960px-LoremIpsum.djvu.jpg 2x" /></a>
 </p>
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"page","ak":"page=2"}]}'><a href="./File:LoremIpsum.djvu" data-parsoid='{"a":{"href":"./File:LoremIpsum.djvu"},"sa":{}}'><img resource="./File:LoremIpsum.djvu" src="//example.com/images/5/5f/LoremIpsum.djvu" height="3508" width="2480" data-parsoid='{"a":{"resource":"./File:LoremIpsum.djvu","height":"3508","width":"2480"},"sa":{"resource":"File:LoremIpsum.djvu"}}'/></a></span></p>
 !! end
 
 !! test
@@ -18156,30 +18384,34 @@ comment
 <a href="/index.php?title=ABC3D%25_%2B%2B&amp;action=edit&amp;redlink=1" class="new" title="ABC3D% ++ (page does not exist)">ABC3D% ++</a> <a href="/index.php?title=ABC3D%25_%2B%2B&amp;action=edit&amp;redlink=1" class="new" title="ABC3D% ++ (page does not exist)">+%20</a>
 !! end
 
-# FIXME: Omitting the php sections here because of differences in the local and
-# jenkins output. But, more importantly, the Bad.jpg isn't being stripped,
-# which seems to be a problem with the testing infrastructure.
+# Parsoid doesn't support this yet: see bug 73581
+# but it *should* omit the 'src' attribute if the image is bad.
+# PHP side of tests was disabled in
+# mediawiki/core:6bd31e7d95161a6e88fa86df60871051da997c3c
+# because of issues in the PHP parserTests infrastructure
+# (but the output below is indeed what the PHP side emits)
 !! test
 Bad images - basic functionality
 !! wikitext
 [[File:Bad.jpg]]
+!! DISABLED/html/php
 !! html/parsoid
-<meta typeof="mw:Placeholder" data-parsoid='{"src":"[[File:Bad.jpg]]","optList":[]}'/>
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"bad-image","message":"This image is blacklisted in this context."}]}'><a href="File:Bad.jpg"><img resource="./File:Bad.jpg" height="220" width="220"/></a></span></p>
 !! end
 
-# FIXME: Same reasoning as above. The expected php is:
-#  <p>Foo bar
-#  </p><p>Bar foo
-#  </p>
 !! test
 Bad images - bug 16039: text after bad image disappears
 !! wikitext
 Foo bar
 [[File:Bad.jpg]]
 Bar foo
+!! DISABLED/html/php
+<p>Foo bar
+</p><p>Bar foo
+</p>
 !! html/parsoid
 <p>Foo bar
-<meta typeof="mw:Placeholder" data-parsoid='{"src":"[[File:Bad.jpg]]","optList":[]}'/>
+<span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"bad-image","message":"This image is blacklisted in this context."}]}'><a href="File:Bad.jpg"><img resource="./File:Bad.jpg" height="220" width="220"/></a></span>
 Bar foo</p>
 !! end
 
@@ -18393,14 +18625,16 @@ percent-encoding and + signs in internal links (Bug 26410)
 !! wikitext
 [[User:+%]] [[Page+title%]]
 [[%+]] [[%+|%20]] [[%+ ]] [[%+r]]
-[[%]] [[+]] [[image:%+abc%39|foo|[[bar]]]]
+[[%]] [[+]] [[File:%+abc%39|foo|[[bar]]]]
 [[%33%45]] [[%33%45+]]
-!! html
+!! html/php
 <p><a href="/index.php?title=User:%2B%25&amp;action=edit&amp;redlink=1" class="new" title="User:+% (page does not exist)">User:+%</a> <a href="/index.php?title=Page%2Btitle%25&amp;action=edit&amp;redlink=1" class="new" title="Page+title% (page does not exist)">Page+title%</a>
 <a href="/index.php?title=%25%2B&amp;action=edit&amp;redlink=1" class="new" title="%+ (page does not exist)">%+</a> <a href="/index.php?title=%25%2B&amp;action=edit&amp;redlink=1" class="new" title="%+ (page does not exist)">%20</a> <a href="/index.php?title=%25%2B&amp;action=edit&amp;redlink=1" class="new" title="%+ (page does not exist)">%+ </a> <a href="/index.php?title=%25%2Br&amp;action=edit&amp;redlink=1" class="new" title="%+r (page does not exist)">%+r</a>
 <a href="/index.php?title=%25&amp;action=edit&amp;redlink=1" class="new" title="% (page does not exist)">%</a> <a href="/index.php?title=%2B&amp;action=edit&amp;redlink=1" class="new" title="+ (page does not exist)">+</a> <a href="/index.php?title=Special:Upload&amp;wpDestFile=%25%2Babc9" class="new" title="File:%+abc9">bar</a>
 <a href="/index.php?title=3E&amp;action=edit&amp;redlink=1" class="new" title="3E (page does not exist)">3E</a> <a href="/index.php?title=3E%2B&amp;action=edit&amp;redlink=1" class="new" title="3E+ (page does not exist)">3E+</a>
 </p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="User:+%" title="User:+%">User:+%</a> <a rel="mw:WikiLink" href="Page+title%" title="Page+title%">Page+title%</a> <a rel="mw:WikiLink" href="%+" title="%+">%+</a> <a rel="mw:WikiLink" href="%+" title="%+">%20</a> <a rel="mw:WikiLink" href="%+" title="%+">%+ </a> <a rel="mw:WikiLink" href="%+r" title="%+r">%+r</a> <a rel="mw:WikiLink" href="%" title="%">%</a> <a rel="mw:WikiLink" href="+" title="+">+</a> <span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"[[bar]]"}'><a href="File:%+abc9"><img resource="./File:%25+abc9" src="./Special:FilePath/%+abc9" height="220" width="220"/></a></span> <a rel="mw:WikiLink" href="3E" title="3E">3E</a> <a rel="mw:WikiLink" href="3E+" title="3E+">3E+</a></p>
 !! end
 
 !! test
@@ -18408,13 +18642,15 @@ Special characters in embedded file links (bug 27679)
 !! wikitext
 [[File:Contains & ampersand.jpg]]
 [[File:Does not exist.jpg|Title with & ampersand]]
-!! html
+!! html/php
 <p><a href="/index.php?title=Special:Upload&amp;wpDestFile=Contains_%26_ampersand.jpg" class="new" title="File:Contains &amp; ampersand.jpg">File:Contains &amp; ampersand.jpg</a>
 <a href="/index.php?title=Special:Upload&amp;wpDestFile=Does_not_exist.jpg" class="new" title="File:Does not exist.jpg">Title with &amp; ampersand</a>
 </p>
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="File:Contains_&amp;_ampersand.jpg"><img resource="./File:Contains_&amp;_ampersand.jpg" src="./Special:FilePath/Contains_&amp;_ampersand.jpg" height="220" width="220"/></a></span>
+<span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"Title with &amp; ampersand"}'><a href="File:Does_not_exist.jpg"><img resource="./File:Does_not_exist.jpg" src="./Special:FilePath/Does_not_exist.jpg" height="220" width="220"/></a></span></p>
 !! end
 
-
 !! test
 Confirm that 'apos' named character reference doesn't make it to output (not legal in HTML 4)
 !! wikitext
@@ -19399,6 +19635,22 @@ A <ref >foo</ref >
 <li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo</li></ol>
 !!end
 
+!!test
+Ref: 17. Generate valid HTML5 id/about attributes
+!!options
+parsoid
+!!wikitext
+<ref name="a b">foo</ref>
+
+<references />
+!!html
+<p><span class="reference" id="cite_ref-a_b-1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"name":"a b"}}'><a href="#cite_note-a_b-1">[1]</a></span>
+</p>
+
+<ol class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'>
+<li id="cite_note-a_b-1"><span rel="mw:referencedBy"><a href="#cite_ref-a_b-1-0">↑</a></span> foo</li>
+!!end
+
 !!test
 References: 1. references tag without any refs should be handled properly
 !!options
@@ -19536,7 +19788,7 @@ parsoid
 !! wikitext
 <ref name="test &amp; me">hi</ref>
 !! html
-<p><span about="#mwt2" class="reference" id="cite_ref-test &amp; me-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"test &amp;amp; me\">hi&lt;/ref>"}' data-mw='{"name":"ref","body":{"html":"hi"},"attrs":{"name":"test &amp; me"}}'><a href="#cite_note-test &amp; me-1">[1]</a></span></p>
+<p><span about="#mwt2" class="reference" id="cite_ref-test_&amp;_me-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"test &amp;amp; me\">hi&lt;/ref>"}' data-mw='{"name":"ref","body":{"html":"hi"},"attrs":{"name":"test &amp; me"}}'><a href="#cite_note-test_&amp;_me-1">[1]</a></span></p>
 !! end
 
 # This test is wt2html only because we're permitting the serializer to produce
@@ -20550,24 +20802,24 @@ ISBN 1234567890's
 !! options
 parsoid=html2wt,wt2wt
 !! wikitext
-''<nowiki>'foo'</nowiki>''
+''<nowiki/>'foo'<nowiki/>''
 ''<nowiki>''foo''</nowiki>''
 ''<nowiki>'''foo'''</nowiki>''
 ''foo''<nowiki/>'s
-'''<nowiki>'foo'</nowiki>'''
+'''<nowiki/>'foo'<nowiki/>'''
 '''<nowiki>''foo''</nowiki>'''
 '''<nowiki>'''foo'''</nowiki>'''
-'''<nowiki>foo'</nowiki>''<nowiki>bar'</nowiki>''baz'''
+'''foo'<nowiki/>''bar'<nowiki/>''baz'''
 '''foo'''<nowiki/>'s
-'''foo''
+'<nowiki/>''foo''
 ''foo''<nowiki/>'
 '<nowiki/>''foo''<nowiki/>'
-''''foo'''
+'<nowiki/>'''foo'''
 '''foo'''<nowiki/>'
 '<nowiki/>'''foo'''<nowiki/>'
 ''fools'<span> errand</span>''
 ''<span>fool</span>'s errand''
-!! html
+!! html/*
 <p><i>'foo'</i>
 <i>''foo''</i>
 <i>'''foo'''</i>
@@ -20582,9 +20834,10 @@ parsoid=html2wt,wt2wt
 '<i>foo</i>'
 '<b>foo</b>
 <b>foo</b>'
-'<b>foo</b>'</p>
+'<b>foo</b>'
 <i>fools'<span> errand</span></i>
 <i><span>fool</span>'s errand</i>
+</p>
 !! end
 
 !! test
@@ -21221,15 +21474,12 @@ parsoid
 
 !!test
 Multi-line image caption generated by templates with/without trailing newlines
-!!options
-parsoid
 !! wikitext
-[[File:foo.jpg|thumb|300px|foo\n{{echo|A}}\n{{echo|B}}\n{{echo|C}}]]
-[[File:foo.jpg|thumb|300px|foo\n{{echo|A}}\n{{echo|B}}\n{{echo|C}}\n\n]]
-!! html
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&amp;wpDestFile=Foo.jpg" class="new" title="File:Foo.jpg">File:Foo.jpg</a>  <div class="thumbcaption">foo\nA\nB\nC</div></div></div>
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&amp;wpDestFile=Foo.jpg" class="new" title="File:Foo.jpg">File:Foo.jpg</a>  <div class="thumbcaption">foo\nA\nB\nC\n\n</div></div></div>
-
+[[File:Foobar.jpg|thumb|300x300px|foo\n{{echo|A}}\n{{echo|B}}\n{{echo|C}}]]
+[[File:Foobar.jpg|thumb|300x300px|foo\n{{echo|A}}\n{{echo|B}}\n{{echo|C}}\n\n]]
+!! html/parsoid
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" height="34" width="300"/></a><figcaption>foo\n<span about="#mwt9" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"A"}},"i":0}}]}'>A</span>\n<span about="#mwt10" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"B"}},"i":0}}]}'>B</span>\n<span about="#mwt11" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"C"}},"i":0}}]}'>C</span></figcaption></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" height="34" width="300"/></a><figcaption>foo\n<span about="#mwt12" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"A"}},"i":0}}]}'>A</span>\n<span about="#mwt13" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"B"}},"i":0}}]}'>B</span>\n<span about="#mwt14" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"C"}},"i":0}}]}'>C</span>\n\n</figcaption></figure>
 !!end
 
 !! test
@@ -21533,6 +21783,17 @@ parsoid=html2wt
 <object data="test.swf"></object>
 !!end
 
+!! test
+Don't block XML namespace declaration
+!! wikitext
+<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">MediaWiki</span>
+!! html/php
+<p><span>MediaWiki</span>
+</p>
+!! html/parsoid
+<p><span xmlns:dct="http://purl.org/dc/terms/" data-x-property="dct:title" data-parsoid='{"stx":"html"}'>MediaWiki</span></p>
+!! end
+
 # -----------------------------------------------------------------
 # The following section of tests are primarily to spec requirements
 # around serialization of new/edited content.
@@ -21551,6 +21812,64 @@ parsoid=html2wt
 <p><a rel="mw:ExtLink" href="http://mi.wikipedia.org/wiki/Foo">Foo</a></p>
 !! end
 
+!! test
+New wiki links (href variations)
+!! options
+parsoid=html2wt
+!! html
+<a rel="mw:WikiLink" href="./Foo_bar">Foo_bar</a>
+<a rel="mw:WikiLink" href="Foo_bar">Foo_bar</a>
+<a rel="mw:WikiLink" href="Foo bar">Foo_bar</a>
+<a rel="mw:WikiLink" href="./Toxine_bact%C3%A9rienne">Toxine bactérienne</a>
+!! wikitext
+[[Foo_bar]]
+[[Foo_bar]]
+[[Foo_bar]]
+[[Toxine bactérienne]]
+!! end
+
+!! test
+New wiki links (content string variations)
+!! options
+parsoid=html2wt
+!! html
+<a rel="mw:WikiLink" href="./Foo_bar">Foo_bar</a>
+<a rel="mw:WikiLink" href="./Foo_bar">Foo bar</a>
+<a rel="mw:WikiLink" href="./Foo_bar">./Foo_bar</a>
+!! wikitext
+[[Foo_bar]]
+[[Foo bar]]
+[[Foo_bar|./Foo_bar]]
+!! end
+
+!! test
+New category links (href variations)
+!! options
+parsoid=html2wt
+!! html
+<link rel="mw:PageProp/Category" href="./Category:Toxine_bactérienne" />
+<link rel="mw:PageProp/Category" href="./Category:Toxine_bact%C3%A9rienne" />
+<link rel="mw:PageProp/Category" href="Category:Toxine_bact%C3%A9rienne" />
+!! wikitext
+[[Category:Toxine bactérienne]]
+[[Category:Toxine bactérienne]]
+[[Category:Toxine bactérienne]]
+!! end
+
+!! test
+New interlanguage links (href variations)
+!! options
+parsoid=html2wt
+!! html
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Toxine bactérienne" />
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Toxine_bactérienne" />
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Toxine_bact%C3%A9rienne" />
+!! wikitext
+[[es:Toxine bactérienne]]
+[[es:Toxine_bactérienne]]
+[[es:Toxine_bactérienne]]
+!! end
+
 !! test
 Image: Modifying size of an image (1)
 !! options
@@ -21693,33 +22012,31 @@ parsoid
 #!! options
 #parsoid=html2wt
 #language=ar
-#!! input
+#!! wikitext
 #[[Imagen:Foobar.jpg|derecha|miniaturadeimagen]]
-#!! result
+#!! html
 #<figure class="mw-default-size mw-halign-right" typeof="mw:Image/Thumb"><a href="Imagen:Foobar.jpg"><img resource="./Imagen:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="20" width="180"/></a></figure>
 #!! end
 
 !! test
 Image: Block level image should have \n before and after
-!! options
-parsoid
 !! wikitext
 123
 [[File:Foobar.jpg|right|thumb|150x150px]]
 456
-!! html
-<p>123</p><figure typeof="mw:Image/Thumb" class="mw-halign-right"><a href="./File:Foobar.png"><img src="http://192.168.142.128/mw/images/thumb/b/bc/Foobar.png/131px-Foobar.png" width="131" height="150" resource="./File:Foobar.png" data-parsoid='{"a":{"resource":"./File:Foobar.png","width":"131"},"sa":{"resource":"File:Foobar.png","width":"150"}}'></a></figure><p>456</p>
+!! html/parsoid
+<p>123</p>
+<figure class="mw-halign-right" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="17" width="150"/></a></figure>
+<p>456</p>
 !!end
 
 !! test
 Image: New block level image should have \n before and after (existing content)
-!! options
-parsoid
 !! wikitext
 123
 [[File:Foobar.jpg|right|thumb|150x150px]]
 456
-!! html
+!! html/parsoid
 <p>123</p>
 <figure class="mw-halign-right" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"right","ak":"right"},{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"150x150px"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/150px-Foobar.jpg" height="17" width="150" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"17","width":"150"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></figure>
 <p>456</p>
@@ -22025,7 +22342,7 @@ parsoid=html2wt
 !! wikitext
 ''A''<i>B</i>
 
-''A'''''<i>B</i>'''
+''A''<nowiki/>'''<i>B</i>'''
 !! html
 <p><i>A</i><i data-parsoid='{"stx":"html"}'>B</i></p>
 <p><i>A</i><b><i data-parsoid='{"stx":"html"}'>B</i></b></p>
@@ -22176,6 +22493,16 @@ parsoid=html2wt
 <link rel="mw:PageProp/redirect" href="Bar" data-parsoid='{"src":"#REDIRECT ","a":{"href":"./Foo"},"sa":{"href":"Foo"}}'>
 !! end
 
+!! test
+T75121: Infer extension name from typeOf if data-mw is not present
+!! options
+parsoid=html2wt
+!! wikitext
+<foo />
+!! html
+<div typeOf="mw:Extension/foo"></div>
+!! end
+
 # -----------------------------------------------------------------
 # End of section for Parsoid-only html2wt tests for serialization
 # of new content
index d075f54..5170856 100644 (file)
@@ -8,10 +8,11 @@
  */
 class ApiFormatWddxTest extends ApiFormatTestBase {
 
-       /**
-        * @requires function wddx_deserialize
-        */
        public function testValidSyntax( ) {
+               if ( !function_exists( 'wddx_deserialize' ) ) {
+                       $this->markTestSkipped( "Function 'wddx_deserialize' not exist, skipping." );
+               }
+
                $data = $this->apiRequest( 'wddx', array( 'action' => 'query', 'meta' => 'siteinfo' ) );
 
                $this->assertInternalType( 'array', wddx_deserialize( $data ) );
index 7571b92..795c2bb 100644 (file)
                assert.equal( $.escapeRE( '0123456789' ), '0123456789', 'escapeRE - Leave numbers alone' );
        } );
 
-       QUnit.test( 'Is functions', 15, function ( assert ) {
-               assert.strictEqual( $.isDomElement( document.getElementById( 'qunit-header' ) ), true,
-                       'isDomElement: #qunit-header Node' );
-               assert.strictEqual( $.isDomElement( document.getElementById( 'random-name' ) ), false,
-                       'isDomElement: #random-name (null)' );
+       QUnit.test( 'isDomElement', 6, function ( assert ) {
+               assert.strictEqual( $.isDomElement( document.createElement( 'div' ) ), true,
+                       'isDomElement: HTMLElement' );
+               assert.strictEqual( $.isDomElement( document.createTextNode( '' ) ), true,
+                       'isDomElement: TextNode' );
+               assert.strictEqual( $.isDomElement( null ), false,
+                       'isDomElement: null' );
                assert.strictEqual( $.isDomElement( document.getElementsByTagName( 'div' ) ), false,
-                       'isDomElement: getElementsByTagName Array' );
-               assert.strictEqual( $.isDomElement( document.getElementsByTagName( 'div' )[0] ), true,
-                       'isDomElement: getElementsByTagName(..)[0] Node' );
+                       'isDomElement: NodeList' );
                assert.strictEqual( $.isDomElement( $( 'div' ) ), false,
-                       'isDomElement: jQuery object' );
-               assert.strictEqual( $.isDomElement( $( 'div' ).get( 0 ) ), true,
-                       'isDomElement: jQuery object > Get node' );
-               assert.strictEqual( $.isDomElement( document.createElement( 'div' ) ), true,
-                       'isDomElement: createElement' );
+                       'isDomElement: jQuery' );
                assert.strictEqual( $.isDomElement( { foo: 1 } ), false,
-                       'isDomElement: Object' );
+                       'isDomElement: Plain Object' );
+       } );
 
+       QUnit.test( 'isEmpty', 7, function ( assert ) {
                assert.strictEqual( $.isEmpty( 'string' ), false, 'isEmpty: "string"' );
                assert.strictEqual( $.isEmpty( '0' ), true, 'isEmpty: "0"' );
                assert.strictEqual( $.isEmpty( '' ), true, 'isEmpty: ""' );